1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
media / audio / alive_checker.h [blame]
// 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::SequencedTaskRunner> 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_