Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(664)

Side by Side Diff: content/browser/media/session/media_session.cc

Issue 1996043002: Split MediaContentType and AudioFocusType (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressed nits Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/media/session/media_session.h" 5 #include "content/browser/media/session/media_session.h"
6 6
7 #include "content/browser/media/session/media_session_delegate.h" 7 #include "content/browser/media/session/media_session_delegate.h"
8 #include "content/browser/media/session/media_session_observer.h" 8 #include "content/browser/media/session/media_session_observer.h"
9 #include "content/browser/web_contents/web_contents_impl.h" 9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/public/browser/web_contents.h" 10 #include "content/public/browser/web_contents.h"
11 #include "content/public/browser/web_contents_delegate.h" 11 #include "content/public/browser/web_contents_delegate.h"
12 #include "media/base/media_content_type.h"
12 13
13 namespace content { 14 namespace content {
14 15
15 namespace { 16 namespace {
16 17
17 const double kDefaultVolumeMultiplier = 1.0; 18 const double kDefaultVolumeMultiplier = 1.0;
18 19
19 } // anonymous namespace 20 } // anonymous namespace
20 21
21 using MediaSessionSuspendedSource = 22 using MediaSessionSuspendedSource =
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 void MediaSession::SetMetadata(const MediaMetadata& metadata) { 62 void MediaSession::SetMetadata(const MediaMetadata& metadata) {
62 metadata_ = metadata; 63 metadata_ = metadata;
63 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the 64 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the
64 // media session play/pause state changes. Need to find a way to seprate the 65 // media session play/pause state changes. Need to find a way to seprate the
65 // state change and Metadata update. See https://crbug.com/621855. 66 // state change and Metadata update. See https://crbug.com/621855.
66 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); 67 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged();
67 } 68 }
68 69
69 bool MediaSession::AddPlayer(MediaSessionObserver* observer, 70 bool MediaSession::AddPlayer(MediaSessionObserver* observer,
70 int player_id, 71 int player_id,
71 Type type) { 72 media::MediaContentType media_content_type) {
72 observer->OnSetVolumeMultiplier(player_id, volume_multiplier_); 73 observer->OnSetVolumeMultiplier(player_id, volume_multiplier_);
73 74
75 // Determine the audio focus type required for playing the new player.
76 // TODO(zqzhang): handle duckable and uncontrollable.
77 // See https://crbug.com/639277.
78 AudioFocusManager::AudioFocusType required_audio_focus_type;
79 if (media_content_type == media::MediaContentType::Persistent) {
80 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain;
81 } else {
82 required_audio_focus_type =
83 AudioFocusManager::AudioFocusType::GainTransientMayDuck;
84 }
85
74 // If the audio focus is already granted and is of type Content, there is 86 // If the audio focus is already granted and is of type Content, there is
75 // nothing to do. If it is granted of type Transient the requested type is 87 // nothing to do. If it is granted of type Transient the requested type is
76 // also transient, there is also nothing to do. Otherwise, the session needs 88 // also transient, there is also nothing to do. Otherwise, the session needs
77 // to request audio focus again. 89 // to request audio focus again.
78 if (audio_focus_state_ == State::ACTIVE && 90 if (audio_focus_state_ == State::ACTIVE &&
79 (audio_focus_type_ == Type::Content || audio_focus_type_ == type)) { 91 (audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain ||
92 audio_focus_type_ == required_audio_focus_type)) {
80 players_.insert(PlayerIdentifier(observer, player_id)); 93 players_.insert(PlayerIdentifier(observer, player_id));
81 return true; 94 return true;
82 } 95 }
83 96
84 State old_audio_focus_state = audio_focus_state_; 97 State old_audio_focus_state = audio_focus_state_;
85 State audio_focus_state = RequestSystemAudioFocus(type) ? State::ACTIVE 98 State audio_focus_state = RequestSystemAudioFocus(required_audio_focus_type)
86 : State::INACTIVE; 99 ? State::ACTIVE
100 : State::INACTIVE;
87 SetAudioFocusState(audio_focus_state); 101 SetAudioFocusState(audio_focus_state);
88 audio_focus_type_ = type; 102 audio_focus_type_ = required_audio_focus_type;
89 103
90 if (audio_focus_state_ != State::ACTIVE) 104 if (audio_focus_state_ != State::ACTIVE)
91 return false; 105 return false;
92 106
93 // The session should be reset if a player is starting while all players are 107 // The session should be reset if a player is starting while all players are
94 // suspended. 108 // suspended.
95 if (old_audio_focus_state != State::ACTIVE) 109 if (old_audio_focus_state != State::ACTIVE)
96 players_.clear(); 110 players_.clear();
97 111
98 players_.insert(PlayerIdentifier(observer, player_id)); 112 players_.insert(PlayerIdentifier(observer, player_id));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 if (players_.size() != 1) { 154 if (players_.size() != 1) {
141 RemovePlayer(observer, player_id); 155 RemovePlayer(observer, player_id);
142 return; 156 return;
143 } 157 }
144 158
145 // Otherwise, suspend the session. 159 // Otherwise, suspend the session.
146 DCHECK(!IsSuspended()); 160 DCHECK(!IsSuspended());
147 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED); 161 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
148 } 162 }
149 163
150 void MediaSession::Resume(SuspendType type) { 164 void MediaSession::Resume(SuspendType suspend_type) {
151 DCHECK(IsReallySuspended()); 165 DCHECK(IsReallySuspended());
152 166
153 // When the resume requests comes from another source than system, audio focus 167 // When the resume requests comes from another source than system, audio focus
154 // must be requested. 168 // must be requested.
155 if (type != SuspendType::SYSTEM) { 169 if (suspend_type != SuspendType::SYSTEM) {
156 // Request audio focus again in case we lost it because another app started 170 // Request audio focus again in case we lost it because another app started
157 // playing while the playback was paused. 171 // playing while the playback was paused.
158 State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_) 172 State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_)
159 ? State::ACTIVE 173 ? State::ACTIVE
160 : State::INACTIVE; 174 : State::INACTIVE;
161 SetAudioFocusState(audio_focus_state); 175 SetAudioFocusState(audio_focus_state);
162 176
163 if (audio_focus_state_ != State::ACTIVE) 177 if (audio_focus_state_ != State::ACTIVE)
164 return; 178 return;
165 } 179 }
166 180
167 OnResumeInternal(type); 181 OnResumeInternal(suspend_type);
168 } 182 }
169 183
170 void MediaSession::Suspend(SuspendType type) { 184 void MediaSession::Suspend(SuspendType suspend_type) {
171 DCHECK(!IsSuspended()); 185 DCHECK(!IsSuspended());
172 186
173 OnSuspendInternal(type, State::SUSPENDED); 187 OnSuspendInternal(suspend_type, State::SUSPENDED);
174 } 188 }
175 189
176 void MediaSession::Stop(SuspendType type) { 190 void MediaSession::Stop(SuspendType suspend_type) {
177 DCHECK(audio_focus_state_ != State::INACTIVE); 191 DCHECK(audio_focus_state_ != State::INACTIVE);
178 192
179 DCHECK(type != SuspendType::CONTENT); 193 DCHECK(suspend_type != SuspendType::CONTENT);
180 194
181 // TODO(mlamouri): merge the logic between UI and SYSTEM. 195 // TODO(mlamouri): merge the logic between UI and SYSTEM.
182 if (type == SuspendType::SYSTEM) { 196 if (suspend_type == SuspendType::SYSTEM) {
183 OnSuspendInternal(type, State::INACTIVE); 197 OnSuspendInternal(suspend_type, State::INACTIVE);
184 return; 198 return;
185 } 199 }
186 200
187 if (audio_focus_state_ != State::SUSPENDED) 201 if (audio_focus_state_ != State::SUSPENDED)
188 OnSuspendInternal(type, State::SUSPENDED); 202 OnSuspendInternal(suspend_type, State::SUSPENDED);
189 203
190 DCHECK(audio_focus_state_ == State::SUSPENDED); 204 DCHECK(audio_focus_state_ == State::SUSPENDED);
191 players_.clear(); 205 players_.clear();
192 AbandonSystemAudioFocusIfNeeded(); 206 AbandonSystemAudioFocusIfNeeded();
193 } 207 }
194 208
195 void MediaSession::SetVolumeMultiplier(double volume_multiplier) { 209 void MediaSession::SetVolumeMultiplier(double volume_multiplier) {
196 volume_multiplier_ = volume_multiplier; 210 volume_multiplier_ = volume_multiplier;
197 for (const auto& it : players_) 211 for (const auto& it : players_)
198 it.observer->OnSetVolumeMultiplier(it.player_id, volume_multiplier_); 212 it.observer->OnSetVolumeMultiplier(it.player_id, volume_multiplier_);
199 } 213 }
200 214
201 bool MediaSession::IsActive() const { 215 bool MediaSession::IsActive() const {
202 return audio_focus_state_ == State::ACTIVE; 216 return audio_focus_state_ == State::ACTIVE;
203 } 217 }
204 218
205 bool MediaSession::IsReallySuspended() const { 219 bool MediaSession::IsReallySuspended() const {
206 return audio_focus_state_ == State::SUSPENDED; 220 return audio_focus_state_ == State::SUSPENDED;
207 } 221 }
208 222
209 bool MediaSession::IsSuspended() const { 223 bool MediaSession::IsSuspended() const {
210 // TODO(mlamouri): should be == State::SUSPENDED. 224 // TODO(mlamouri): should be == State::SUSPENDED.
211 return audio_focus_state_ != State::ACTIVE; 225 return audio_focus_state_ != State::ACTIVE;
212 } 226 }
213 227
214 bool MediaSession::IsControllable() const { 228 bool MediaSession::IsControllable() const {
215 // Only content type media session can be controllable unless it is inactive. 229 // Only media session having focus Gain can be controllable unless it is
230 // inactive.
216 return audio_focus_state_ != State::INACTIVE && 231 return audio_focus_state_ != State::INACTIVE &&
217 audio_focus_type_ == Type::Content; 232 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain;
218 } 233 }
219 234
220 std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription> 235 std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
221 MediaSession::RegisterMediaSessionStateChangedCallbackForTest( 236 MediaSession::RegisterMediaSessionStateChangedCallbackForTest(
222 const StateChangedCallback& cb) { 237 const StateChangedCallback& cb) {
223 return media_session_state_listeners_.Add(cb); 238 return media_session_state_listeners_.Add(cb);
224 } 239 }
225 240
226 void MediaSession::SetDelegateForTests( 241 void MediaSession::SetDelegateForTests(
227 std::unique_ptr<MediaSessionDelegate> delegate) { 242 std::unique_ptr<MediaSessionDelegate> delegate) {
228 delegate_ = std::move(delegate); 243 delegate_ = std::move(delegate);
229 } 244 }
230 245
231 bool MediaSession::IsActiveForTest() const { 246 bool MediaSession::IsActiveForTest() const {
232 return audio_focus_state_ == State::ACTIVE; 247 return audio_focus_state_ == State::ACTIVE;
233 } 248 }
234 249
235 MediaSession::Type MediaSession::audio_focus_type_for_test() const { 250 AudioFocusManager::AudioFocusType MediaSession::audio_focus_type_for_test()
251 const {
236 return audio_focus_type_; 252 return audio_focus_type_;
237 } 253 }
238 254
239 MediaSessionUmaHelper* MediaSession::uma_helper_for_test() { 255 MediaSessionUmaHelper* MediaSession::uma_helper_for_test() {
240 return &uma_helper_; 256 return &uma_helper_;
241 } 257 }
242 258
243 void MediaSession::RemoveAllPlayersForTest() { 259 void MediaSession::RemoveAllPlayersForTest() {
244 players_.clear(); 260 players_.clear();
245 AbandonSystemAudioFocusIfNeeded(); 261 AbandonSystemAudioFocusIfNeeded();
246 } 262 }
247 263
248 void MediaSession::OnSuspendInternal(SuspendType type, State new_state) { 264 void MediaSession::OnSuspendInternal(SuspendType suspend_type,
265 State new_state) {
249 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); 266 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE);
250 // UI suspend cannot use State::INACTIVE. 267 // UI suspend cannot use State::INACTIVE.
251 DCHECK(type == SuspendType::SYSTEM || new_state == State::SUSPENDED); 268 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
252 269
253 if (audio_focus_state_ != State::ACTIVE) 270 if (audio_focus_state_ != State::ACTIVE)
254 return; 271 return;
255 272
256 switch (type) { 273 switch (suspend_type) {
257 case SuspendType::UI: 274 case SuspendType::UI:
258 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); 275 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI);
259 break; 276 break;
260 case SuspendType::SYSTEM: 277 case SuspendType::SYSTEM:
261 switch (new_state) { 278 switch (new_state) {
262 case State::SUSPENDED: 279 case State::SUSPENDED:
263 uma_helper_.RecordSessionSuspended( 280 uma_helper_.RecordSessionSuspended(
264 MediaSessionSuspendedSource::SystemTransient); 281 MediaSessionSuspendedSource::SystemTransient);
265 break; 282 break;
266 case State::INACTIVE: 283 case State::INACTIVE:
267 uma_helper_.RecordSessionSuspended( 284 uma_helper_.RecordSessionSuspended(
268 MediaSessionSuspendedSource::SystemPermanent); 285 MediaSessionSuspendedSource::SystemPermanent);
269 break; 286 break;
270 case State::ACTIVE: 287 case State::ACTIVE:
271 NOTREACHED(); 288 NOTREACHED();
272 break; 289 break;
273 } 290 }
274 break; 291 break;
275 case SuspendType::CONTENT: 292 case SuspendType::CONTENT:
276 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::CONTENT); 293 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::CONTENT);
277 break; 294 break;
278 } 295 }
279 296
280 SetAudioFocusState(new_state); 297 SetAudioFocusState(new_state);
281 suspend_type_ = type; 298 suspend_type_ = suspend_type;
282 299
283 if (type != SuspendType::CONTENT) { 300 if (suspend_type != SuspendType::CONTENT) {
284 // SuspendType::CONTENT happens when the suspend action came from 301 // SuspendType::CONTENT happens when the suspend action came from
285 // the page in which case the player is already paused. 302 // the page in which case the player is already paused.
286 // Otherwise, the players need to be paused. 303 // Otherwise, the players need to be paused.
287 for (const auto& it : players_) 304 for (const auto& it : players_)
288 it.observer->OnSuspend(it.player_id); 305 it.observer->OnSuspend(it.player_id);
289 } 306 }
290 307
291 UpdateWebContents(); 308 UpdateWebContents();
292 } 309 }
293 310
294 void MediaSession::OnResumeInternal(SuspendType type) { 311 void MediaSession::OnResumeInternal(SuspendType suspend_type) {
295 if (type == SuspendType::SYSTEM && suspend_type_ != type) 312 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type)
296 return; 313 return;
297 314
298 SetAudioFocusState(State::ACTIVE); 315 SetAudioFocusState(State::ACTIVE);
299 316
300 for (const auto& it : players_) 317 for (const auto& it : players_)
301 it.observer->OnResume(it.player_id); 318 it.observer->OnResume(it.player_id);
302 319
303 UpdateWebContents(); 320 UpdateWebContents();
304 } 321 }
305 322
306 MediaSession::MediaSession(WebContents* web_contents) 323 MediaSession::MediaSession(WebContents* web_contents)
307 : WebContentsObserver(web_contents), 324 : WebContentsObserver(web_contents),
308 audio_focus_state_(State::INACTIVE), 325 audio_focus_state_(State::INACTIVE),
309 audio_focus_type_(Type::Transient), 326 audio_focus_type_(
310 volume_multiplier_(kDefaultVolumeMultiplier) { 327 AudioFocusManager::AudioFocusType::GainTransientMayDuck),
311 } 328 volume_multiplier_(kDefaultVolumeMultiplier) {}
312 329
313 void MediaSession::Initialize() { 330 void MediaSession::Initialize() {
314 delegate_ = MediaSessionDelegate::Create(this); 331 delegate_ = MediaSessionDelegate::Create(this);
315 } 332 }
316 333
317 bool MediaSession::RequestSystemAudioFocus(Type type) { 334 bool MediaSession::RequestSystemAudioFocus(
318 bool result = delegate_->RequestAudioFocus(type); 335 AudioFocusManager::AudioFocusType audio_focus_type) {
336 bool result = delegate_->RequestAudioFocus(audio_focus_type);
319 uma_helper_.RecordRequestAudioFocusResult(result); 337 uma_helper_.RecordRequestAudioFocusResult(result);
320 return result; 338 return result;
321 } 339 }
322 340
323 void MediaSession::AbandonSystemAudioFocusIfNeeded() { 341 void MediaSession::AbandonSystemAudioFocusIfNeeded() {
324 if (audio_focus_state_ == State::INACTIVE || !players_.empty()) 342 if (audio_focus_state_ == State::INACTIVE || !players_.empty())
325 return; 343 return;
326 344
327 delegate_->AbandonAudioFocus(); 345 delegate_->AbandonAudioFocus();
328 346
(...skipping 18 matching lines...) Expand all
347 case State::SUSPENDED: 365 case State::SUSPENDED:
348 uma_helper_.OnSessionSuspended(); 366 uma_helper_.OnSessionSuspended();
349 break; 367 break;
350 case State::INACTIVE: 368 case State::INACTIVE:
351 uma_helper_.OnSessionInactive(); 369 uma_helper_.OnSessionInactive();
352 break; 370 break;
353 } 371 }
354 } 372 }
355 373
356 } // namespace content 374 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/session/media_session.h ('k') | content/browser/media/session/media_session_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698