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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
ash / media / media_controller_impl.h [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_MEDIA_MEDIA_CONTROLLER_IMPL_H_
#define ASH_MEDIA_MEDIA_CONTROLLER_IMPL_H_
#include "ash/ash_export.h"
#include "ash/public/cpp/media_controller.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "components/account_id/account_id.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/public/mojom/media_controller.mojom.h"
class PrefRegistrySimple;
namespace ash {
class MediaClient;
// Forwards notifications from the MediaController to observers.
class MediaCaptureObserver {
public:
// Called when media capture state has changed.
virtual void OnMediaCaptureChanged(
const base::flat_map<AccountId, MediaCaptureState>& capture_states) {}
// Called when VMs' media capture notifications change. Each VM can have 0 or
// 1 media notification. It can either be a "camera", "mic", or "camera and
// mic" notification. Each of the argument is true if a notification of the
// corresponding type is active.
virtual void OnVmMediaNotificationChanged(bool camera,
bool mic,
bool camera_and_mic) {}
protected:
virtual ~MediaCaptureObserver() {}
};
// Provides the MediaController interface to the outside world. This lets a
// consumer of ash provide a MediaClient, which we will dispatch to if one has
// been provided to us.
class ASH_EXPORT MediaControllerImpl
: public MediaController,
public media_session::mojom::MediaControllerObserver {
public:
MediaControllerImpl();
MediaControllerImpl(const MediaControllerImpl&) = delete;
MediaControllerImpl& operator=(const MediaControllerImpl&) = delete;
~MediaControllerImpl() override;
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
media_session::mojom::MediaSessionInfoPtr GetMediaSessionInfo() const {
return media_session_info_ ? media_session_info_->Clone() : nullptr;
}
// Determine if lock screen media keys are enabled.
bool AreLockScreenMediaKeysEnabled() const;
void SetMediaControlsDismissed(bool media_controls_dismissed);
void AddObserver(MediaCaptureObserver* observer);
void RemoveObserver(MediaCaptureObserver* observer);
// MediaController:
void SetClient(MediaClient* client) override;
void SetForceMediaClientKeyHandling(bool enabled) override;
void NotifyCaptureState(const base::flat_map<AccountId, MediaCaptureState>&
capture_states) override;
void NotifyVmMediaNotificationState(bool camera,
bool mic,
bool camera_and_mic) override;
// If media session accelerators are enabled then these methods will use the
// media session service to control playback. Otherwise it will forward to
// |client_|.
void HandleMediaPlayPause();
void HandleMediaPlay();
void HandleMediaPause();
void HandleMediaStop();
void HandleMediaNextTrack();
void HandleMediaPrevTrack();
void HandleMediaSeekBackward();
void HandleMediaSeekForward();
// Methods that forward to |client_|.
void RequestCaptureState();
void SuspendMediaSessions();
// media_session::mojom::MediaControllerObserver:
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) override;
void MediaSessionMetadataChanged(
const std::optional<media_session::MediaMetadata>& metadata) override {}
void MediaSessionActionsChanged(
const std::vector<media_session::mojom::MediaSessionAction>& actions)
override;
void MediaSessionChanged(
const std::optional<base::UnguessableToken>& request_id) override {}
void MediaSessionPositionChanged(
const std::optional<media_session::MediaPosition>& position) override {}
private:
friend class MediaControllerTest;
friend class MediaSessionAcceleratorTest;
friend class MultiProfileMediaTrayItemTest;
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_NextTrack);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_Play);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_Pause);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_PrevTrack);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_UpdateAction_Disable);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_UpdateAction_Enable);
FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
MediaGlobalAccelerators_UpdateForceKeyHandling);
void SetMediaSessionControllerForTest(
mojo::Remote<media_session::mojom::MediaController> controller);
void FlushForTesting();
// Returns a pointer to the active media session controller.
media_session::mojom::MediaController* GetMediaSessionController();
void OnMediaSessionControllerError();
void BindMediaControllerObserver();
// Returns true if we should use the media session service for key handling.
bool ShouldUseMediaSession();
void ResetForceMediaClientKeyHandling();
// Whether the active media session currently supports any action that has a
// media key.
bool supported_media_session_action_ = false;
// The info about the current media session. It will be null if there is not
// a current session.
media_session::mojom::MediaSessionInfoPtr media_session_info_;
// If true then the media keys should be forwarded to the client instead of
// being handled in ash.
bool force_media_client_key_handling_ = false;
// Whether the lock screen media controls are dismissed.
bool media_controls_dismissed_ = false;
// Mojo pointer to the active media session controller.
mojo::Remote<media_session::mojom::MediaController>
media_session_controller_remote_;
mojo::Receiver<media_session::mojom::MediaControllerObserver>
media_controller_observer_receiver_{this};
raw_ptr<MediaClient> client_ = nullptr;
base::ObserverList<MediaCaptureObserver>::Unchecked observers_;
};
} // namespace ash
#endif // ASH_MEDIA_MEDIA_CONTROLLER_IMPL_H_