alive_checker.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2017 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 "media/audio/alive_checker.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/threading/thread_task_runner_handle.h"
  9. namespace media {
  10. AliveChecker::AliveChecker(base::RepeatingClosure dead_callback,
  11. base::TimeDelta check_interval,
  12. base::TimeDelta timeout,
  13. bool stop_at_first_alive_notification,
  14. bool pause_check_during_suspend)
  15. : AliveChecker(std::move(dead_callback),
  16. check_interval,
  17. timeout,
  18. stop_at_first_alive_notification,
  19. pause_check_during_suspend,
  20. PowerObserverHelperFactoryCallback()) {}
  21. AliveChecker::AliveChecker(
  22. base::RepeatingClosure dead_callback,
  23. base::TimeDelta check_interval,
  24. base::TimeDelta timeout,
  25. bool stop_at_first_alive_notification,
  26. PowerObserverHelperFactoryCallback power_observer_helper_factory_callback)
  27. : AliveChecker(std::move(dead_callback),
  28. check_interval,
  29. timeout,
  30. stop_at_first_alive_notification,
  31. true,
  32. std::move(power_observer_helper_factory_callback)) {}
  33. // The private constructor called by the above public constructors.
  34. AliveChecker::AliveChecker(
  35. base::RepeatingClosure dead_callback,
  36. base::TimeDelta check_interval,
  37. base::TimeDelta timeout,
  38. bool stop_at_first_alive_notification,
  39. bool pause_check_during_suspend,
  40. PowerObserverHelperFactoryCallback power_observer_helper_factory_callback)
  41. : check_interval_(check_interval),
  42. timeout_(timeout),
  43. task_runner_(base::ThreadTaskRunnerHandle::Get()),
  44. dead_callback_(std::move(dead_callback)),
  45. stop_at_first_alive_notification_(stop_at_first_alive_notification) {
  46. DCHECK(!dead_callback_.is_null());
  47. DCHECK_GT(check_interval_, base::TimeDelta());
  48. DCHECK_GT(timeout_, check_interval_);
  49. if (pause_check_during_suspend) {
  50. // When suspending, we don't need to take any action. When resuming, we
  51. // reset |last_alive_notification_time_| to avoid false alarms.
  52. // Unretained is safe since the PowerObserverHelper runs the callback on
  53. // the task runner the AliveChecker (and consequently the
  54. // PowerObserverHelper) is destroyed on.
  55. if (power_observer_helper_factory_callback.is_null()) {
  56. power_observer_ = std::make_unique<PowerObserverHelper>(
  57. task_runner_, base::DoNothing(),
  58. base::BindRepeating(
  59. &AliveChecker::SetLastAliveNotificationTimeToNowOnTaskRunner,
  60. base::Unretained(this)));
  61. } else {
  62. power_observer_ =
  63. std::move(power_observer_helper_factory_callback)
  64. .Run(task_runner_, base::DoNothing(),
  65. base::BindRepeating(
  66. &AliveChecker::
  67. SetLastAliveNotificationTimeToNowOnTaskRunner,
  68. base::Unretained(this)));
  69. }
  70. } else {
  71. // If |pause_check_during_suspend| is false, we expect an empty factory
  72. // callback.
  73. DCHECK(power_observer_helper_factory_callback.is_null());
  74. }
  75. }
  76. AliveChecker::~AliveChecker() {
  77. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  78. }
  79. void AliveChecker::Start() {
  80. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  81. SetLastAliveNotificationTimeToNowOnTaskRunner();
  82. detected_dead_ = false;
  83. DCHECK(!check_alive_timer_);
  84. check_alive_timer_ = std::make_unique<base::RepeatingTimer>();
  85. check_alive_timer_->Start(FROM_HERE, check_interval_, this,
  86. &AliveChecker::CheckIfAlive);
  87. DCHECK(check_alive_timer_->IsRunning());
  88. }
  89. void AliveChecker::Stop() {
  90. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  91. check_alive_timer_.reset();
  92. }
  93. bool AliveChecker::DetectedDead() {
  94. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  95. return detected_dead_;
  96. }
  97. void AliveChecker::NotifyAlive() {
  98. if (!task_runner_->RunsTasksInCurrentSequence()) {
  99. // We don't need high precision for setting |last_alive_notification_time_|
  100. // so we don't have to care about the delay added with posting the task.
  101. task_runner_->PostTask(
  102. FROM_HERE,
  103. base::BindOnce(&AliveChecker::NotifyAlive, weak_factory_.GetWeakPtr()));
  104. return;
  105. }
  106. SetLastAliveNotificationTimeToNowOnTaskRunner();
  107. if (stop_at_first_alive_notification_)
  108. Stop();
  109. }
  110. void AliveChecker::CheckIfAlive() {
  111. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  112. // The reason we check a flag instead of stopping the timer that runs this
  113. // function at suspend is that it would require knowing what state we're in
  114. // when resuming and maybe start the timer. Also, we would still need this
  115. // flag anyway to maybe start the timer at stream creation.
  116. // TODO(grunell): Suspend/resume notifications are not supported on Linux. We
  117. // could possibly use wall clock time as a complement to be able to detect
  118. // time jumps that probably are caused by suspend/resume.
  119. if (power_observer_ && power_observer_->IsSuspending())
  120. return;
  121. if (base::TimeTicks::Now() - last_alive_notification_time_ > timeout_) {
  122. Stop();
  123. detected_dead_ = true;
  124. dead_callback_.Run();
  125. }
  126. }
  127. void AliveChecker::SetLastAliveNotificationTimeToNowOnTaskRunner() {
  128. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  129. last_alive_notification_time_ = base::TimeTicks::Now();
  130. }
  131. } // namespace media