connection_scheduler_impl.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/components/phonehub/connection_scheduler_impl.h"
  5. #include "ash/components/multidevice/logging/logging.h"
  6. #include "ash/components/phonehub/feature_status.h"
  7. #include "ash/services/secure_channel/public/cpp/client/connection_manager.h"
  8. #include "base/bind.h"
  9. #include "base/threading/sequenced_task_runner_handle.h"
  10. namespace ash {
  11. namespace phonehub {
  12. constexpr net::BackoffEntry::Policy kRetryBackoffPolicy = {
  13. 0, // Number of initial errors to ignore.
  14. 10 * 1000, // Initial delay of 10 seconds in ms.
  15. 2.0, // Factor by which the waiting time will be multiplied.
  16. 0.2, // Fuzzing percentage.
  17. 60 * 60 * 1000, // Maximum delay of 1 hour in ms.
  18. -1, // Never discard the entry.
  19. true, // Use initial delay.
  20. };
  21. ConnectionSchedulerImpl::ConnectionSchedulerImpl(
  22. secure_channel::ConnectionManager* connection_manager,
  23. FeatureStatusProvider* feature_status_provider)
  24. : connection_manager_(connection_manager),
  25. feature_status_provider_(feature_status_provider),
  26. retry_backoff_(&kRetryBackoffPolicy) {
  27. DCHECK(connection_manager_);
  28. DCHECK(feature_status_provider_);
  29. current_feature_status_ = feature_status_provider_->GetStatus();
  30. feature_status_provider_->AddObserver(this);
  31. }
  32. ConnectionSchedulerImpl::~ConnectionSchedulerImpl() {
  33. feature_status_provider_->RemoveObserver(this);
  34. weak_ptr_factory_.InvalidateWeakPtrs();
  35. }
  36. void ConnectionSchedulerImpl::ScheduleConnectionNow() {
  37. if (feature_status_provider_->GetStatus() !=
  38. FeatureStatus::kEnabledButDisconnected) {
  39. PA_LOG(WARNING) << "ScheduleConnectionNow() could not request a connection "
  40. << "attempt because the current status is: "
  41. << feature_status_provider_->GetStatus() << ".";
  42. return;
  43. }
  44. connection_manager_->AttemptNearbyConnection();
  45. }
  46. void ConnectionSchedulerImpl::OnFeatureStatusChanged() {
  47. const FeatureStatus previous_feature_status = current_feature_status_;
  48. current_feature_status_ = feature_status_provider_->GetStatus();
  49. switch (current_feature_status_) {
  50. // The following feature states indicate that there is an interruption with
  51. // establishing connection to the host phone or that the feature is blocked
  52. // from initiating a connection. Disconnect the existing connection, reset
  53. // backoffs, and return early.
  54. case FeatureStatus::kNotEligibleForFeature:
  55. [[fallthrough]];
  56. case FeatureStatus::kEligiblePhoneButNotSetUp:
  57. [[fallthrough]];
  58. case FeatureStatus::kPhoneSelectedAndPendingSetup:
  59. [[fallthrough]];
  60. case FeatureStatus::kDisabled:
  61. [[fallthrough]];
  62. case FeatureStatus::kUnavailableBluetoothOff:
  63. [[fallthrough]];
  64. case FeatureStatus::kLockOrSuspended:
  65. DisconnectAndClearBackoffAttempts();
  66. return;
  67. // Connection has been established, clear existing backoffs and return
  68. // early.
  69. case FeatureStatus::kEnabledAndConnected:
  70. ClearBackoffAttempts();
  71. return;
  72. // Connection is in progress, return and wait for the result.
  73. case FeatureStatus::kEnabledAndConnecting:
  74. return;
  75. // Phone is available for connection, attempt to establish connection.
  76. case FeatureStatus::kEnabledButDisconnected:
  77. break;
  78. }
  79. if (previous_feature_status == FeatureStatus::kEnabledAndConnecting) {
  80. PA_LOG(WARNING) << "Scheduling connection to retry in: "
  81. << retry_backoff_.GetTimeUntilRelease().InSeconds()
  82. << " seconds.";
  83. retry_backoff_.InformOfRequest(/*succeeded=*/false);
  84. base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
  85. FROM_HERE,
  86. base::BindOnce(&ConnectionSchedulerImpl::ScheduleConnectionNow,
  87. weak_ptr_factory_.GetWeakPtr()),
  88. retry_backoff_.GetTimeUntilRelease());
  89. } else {
  90. PA_LOG(VERBOSE) << "Feature status has been updated to "
  91. << "kEnabledButDisconnected, scheduling connection now.";
  92. // Schedule connection now without a delay.
  93. ScheduleConnectionNow();
  94. }
  95. }
  96. void ConnectionSchedulerImpl::ClearBackoffAttempts() {
  97. // Remove all pending ScheduleConnectionNow() backoff attempts.
  98. weak_ptr_factory_.InvalidateWeakPtrs();
  99. // Reset the state of the backoff so that the next backoff retry starts at
  100. // the default initial delay.
  101. retry_backoff_.Reset();
  102. }
  103. void ConnectionSchedulerImpl::DisconnectAndClearBackoffAttempts() {
  104. ClearBackoffAttempts();
  105. // Disconnect existing connection or connection attempt.
  106. connection_manager_->Disconnect();
  107. }
  108. base::TimeDelta
  109. ConnectionSchedulerImpl::GetCurrentBackoffDelayTimeForTesting() {
  110. return retry_backoff_.GetTimeUntilRelease();
  111. }
  112. int ConnectionSchedulerImpl::GetBackoffFailureCountForTesting() {
  113. return retry_backoff_.failure_count();
  114. }
  115. } // namespace phonehub
  116. } // namespace ash