| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef MEDIA_AUDIO_ALIVE_CHECKER_H_ |
| #define MEDIA_AUDIO_ALIVE_CHECKER_H_ |
| |
| #include <memory> |
| |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "media/audio/power_observer_helper.h" |
| #include "media/base/media_export.h" |
| |
| namespace media { |
| |
| // A class that checks if a client that is expected to have regular activity |
| // is alive. For example, audio streams expect regular callbacks from the |
| // operating system. The client informs regularly that it's alive by calling |
| // NotifyAlive(). At a certain interval the AliveChecker checks that it has been |
| // notified within a timeout period. If not, it runs a callback to inform about |
| // detecting dead. The callback is run once and further checking is stopped at |
| // detection. Checking can be restarted if desired. |
| // |
| // The AliveChecker can pause checking when the machine is suspending, i.e. |
| // between suspend and resume notification from base::PowerMonitor. Checking |
| // during this period can cause false positives. Shorter timeout gives higher |
| // risk of false positives. |
| // |
| // It lives on the task runner it's created on; all functions except |
| // NotifyAlive() must be called on it. NotifyAlive() can be called on any task |
| // runner. |
| // |
| // It stops at the first NotifyAlive() call if |
| // |stop_at_first_alive_notification| is specified at construction time. This |
| // can be useful for example if the platform doesn't support suspend/resume |
| // notifications, as Linux. |
| class MEDIA_EXPORT AliveChecker { |
| public: |
| // Factory callback to create a PowerObserverHelper that can be injected. Can |
| // be used by tests to provide a mock. |
| using PowerObserverHelperFactoryCallback = |
| base::OnceCallback<std::unique_ptr<PowerObserverHelper>( |
| scoped_refptr<base::SequencedTaskRunner> task_runner, |
| base::RepeatingClosure suspend_callback, |
| base::RepeatingClosure resume_callback)>; |
| |
| // See class description for general explanation of parameters. |
| // In addition the following must be true: |timeout| > |check_interval| > 0. |
| // The first version creates a PowerObserverHelper internally, the second |
| // version takes a factory callback to allow injecting a PowerObserverHelper, |
| // typically a mock for testing. The callback is run in the constructor. The |
| // second version doesn't have |pause_check_during_suspend|, since that's |
| // implicitly true when providing a PowerObserverHelper. |
| AliveChecker(base::RepeatingClosure dead_callback, |
| base::TimeDelta check_interval, |
| base::TimeDelta timeout, |
| bool stop_at_first_alive_notification, |
| bool pause_check_during_suspend); |
| AliveChecker(base::RepeatingClosure dead_callback, |
| base::TimeDelta check_interval, |
| base::TimeDelta timeout, |
| bool stop_at_first_alive_notification, |
| PowerObserverHelperFactoryCallback |
| power_observer_helper_factory_callback); |
| |
| AliveChecker(const AliveChecker&) = delete; |
| AliveChecker& operator=(const AliveChecker&) = delete; |
| |
| ~AliveChecker(); |
| |
| // Start and stop checking if the client is alive. |
| void Start(); |
| void Stop(); |
| |
| // Returns whether dead was detected. Reset when Start() is called. |
| bool DetectedDead(); |
| |
| // Called regularly by the client to inform that it's alive. Can be called on |
| // any thread. |
| void NotifyAlive(); |
| |
| private: |
| // Internal version called by the public constructors, to keep the interface |
| // and contract clear in the public versions. |
| AliveChecker(base::RepeatingClosure dead_callback, |
| base::TimeDelta check_interval, |
| base::TimeDelta timeout, |
| bool stop_at_first_alive_notification, |
| bool pause_check_during_suspend, |
| PowerObserverHelperFactoryCallback |
| power_observer_helper_factory_callback); |
| |
| // Checks if we have gotten an alive notification within a certain time |
| // period. If not, run |dead_callback_|. |
| void CheckIfAlive(); |
| |
| // Sets |last_alive_notification_time_| to the current time. |
| void SetLastAliveNotificationTimeToNowOnTaskRunner(); |
| |
| // Timer to run the check regularly. |
| std::unique_ptr<base::RepeatingTimer> check_alive_timer_; |
| |
| // Stores the time NotifyAlive() was last called. |
| // TODO(grunell): Change from TimeTicks to Atomic32 and remove the task |
| // posting in NotifyAlive(). The Atomic32 variable would have to |
| // represent some time in seconds or tenths of seconds to be able to span over |
| // enough time. Atomic64 cannot be used since it's not supported on 32-bit |
| // platforms. |
| base::TimeTicks last_alive_notification_time_; |
| |
| // The interval at which we check if alive. |
| const base::TimeDelta check_interval_; |
| |
| // The time interval since |last_alive_notification_time_| after which we |
| // decide the client is dead and run |dead_callback_|. |
| const base::TimeDelta timeout_; |
| |
| // Flags that dead was detected. Set in CheckIfAlive() if we have decided that |
| // the client is dead. Cleared in Start(). |
| bool detected_dead_ = false; |
| |
| // The task runner on which this object lives. |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| |
| // Dead notification callback. |
| base::RepeatingClosure dead_callback_; |
| |
| // If true, checking stops after first alive notification, otherwise continues |
| // until Stop() is called or the client is decided to be dead. |
| const bool stop_at_first_alive_notification_; |
| |
| // Used for getting suspend/resume notifications. |
| std::unique_ptr<PowerObserverHelper> power_observer_; |
| |
| base::WeakPtrFactory<AliveChecker> weak_factory_{this}; |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_AUDIO_ALIVE_CHECKER_H_ |