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

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

Issue 2382723006: Revert of Letting Flash join MediaSession (stack implementaion) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@media_session_type
Patch Set: Created 4 years, 2 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"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 session->Initialize(); 53 session->Initialize();
54 } 54 }
55 return session; 55 return session;
56 } 56 }
57 57
58 MediaSession::~MediaSession() { 58 MediaSession::~MediaSession() {
59 DCHECK(players_.empty()); 59 DCHECK(players_.empty());
60 DCHECK(audio_focus_state_ == State::INACTIVE); 60 DCHECK(audio_focus_state_ == State::INACTIVE);
61 } 61 }
62 62
63 void MediaSession::WebContentsDestroyed() {
64 // This should only work for tests. In production, all the players should have
65 // already been removed before WebContents is destroyed.
66
67 // TODO(zqzhang): refactor MediaSession, maybe move the interface used to talk
68 // with AudioFocusManager out to a seperate class. The AudioFocusManager unit
69 // tests then could mock the interface and abandon audio focus when
70 // WebContents is destroyed. See https://crbug.com/651069
71 players_.clear();
72 pepper_players_.clear();
73 AbandonSystemAudioFocusIfNeeded();
74 }
75
76 void MediaSession::SetMetadata(const base::Optional<MediaMetadata>& metadata) { 63 void MediaSession::SetMetadata(const base::Optional<MediaMetadata>& metadata) {
77 metadata_ = metadata; 64 metadata_ = metadata;
78 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the 65 // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the
79 // media session play/pause state changes. Need to find a way to seprate the 66 // media session play/pause state changes. Need to find a way to seprate the
80 // state change and Metadata update. See https://crbug.com/621855. 67 // state change and Metadata update. See https://crbug.com/621855.
81 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); 68 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged();
82 } 69 }
83 70
84 bool MediaSession::AddPlayer(MediaSessionObserver* observer, 71 bool MediaSession::AddPlayer(MediaSessionObserver* observer,
85 int player_id, 72 int player_id,
86 media::MediaContentType media_content_type) { 73 media::MediaContentType media_content_type) {
87 if (media_content_type == media::MediaContentType::Pepper)
88 return AddPepperPlayer(observer, player_id);
89
90 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); 74 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
91 75
92 // Determine the audio focus type required for playing the new player. 76 // Determine the audio focus type required for playing the new player.
93 // TODO(zqzhang): handle duckable and uncontrollable. 77 // TODO(zqzhang): handle duckable and uncontrollable.
94 // See https://crbug.com/639277. 78 // See https://crbug.com/639277.
95 AudioFocusManager::AudioFocusType required_audio_focus_type; 79 AudioFocusManager::AudioFocusType required_audio_focus_type;
96 if (media_content_type == media::MediaContentType::Persistent) { 80 if (media_content_type == media::MediaContentType::Persistent) {
97 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; 81 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain;
98 } else { 82 } else {
99 required_audio_focus_type = 83 required_audio_focus_type =
100 AudioFocusManager::AudioFocusType::GainTransientMayDuck; 84 AudioFocusManager::AudioFocusType::GainTransientMayDuck;
101 } 85 }
102 86
103 // If the audio focus is already granted and is of type Content, there is 87 // If the audio focus is already granted and is of type Content, there is
104 // nothing to do. If it is granted of type Transient the requested type is 88 // nothing to do. If it is granted of type Transient the requested type is
105 // also transient, there is also nothing to do. Otherwise, the session needs 89 // also transient, there is also nothing to do. Otherwise, the session needs
106 // to request audio focus again. 90 // to request audio focus again.
107 if (audio_focus_state_ == State::ACTIVE && 91 if (audio_focus_state_ == State::ACTIVE &&
108 (audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain || 92 (audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain ||
109 audio_focus_type_ == required_audio_focus_type)) { 93 audio_focus_type_ == required_audio_focus_type)) {
110 players_.insert(PlayerIdentifier(observer, player_id)); 94 players_.insert(PlayerIdentifier(observer, player_id));
111 return true; 95 return true;
112 } 96 }
113 97
114 State old_audio_focus_state = audio_focus_state_; 98 State old_audio_focus_state = audio_focus_state_;
115 RequestSystemAudioFocus(required_audio_focus_type); 99 State audio_focus_state = RequestSystemAudioFocus(required_audio_focus_type)
100 ? State::ACTIVE
101 : State::INACTIVE;
102 SetAudioFocusState(audio_focus_state);
103 audio_focus_type_ = required_audio_focus_type;
116 104
117 if (audio_focus_state_ != State::ACTIVE) 105 if (audio_focus_state_ != State::ACTIVE)
118 return false; 106 return false;
119 107
120 // The session should be reset if a player is starting while all players are 108 // The session should be reset if a player is starting while all players are
121 // suspended. 109 // suspended.
122 if (old_audio_focus_state != State::ACTIVE) 110 if (old_audio_focus_state != State::ACTIVE)
123 players_.clear(); 111 players_.clear();
124 112
125 players_.insert(PlayerIdentifier(observer, player_id)); 113 players_.insert(PlayerIdentifier(observer, player_id));
126 UpdateWebContents(); 114 UpdateWebContents();
127 115
128 return true; 116 return true;
129 } 117 }
130 118
131 void MediaSession::RemovePlayer(MediaSessionObserver* observer, 119 void MediaSession::RemovePlayer(MediaSessionObserver* observer,
132 int player_id) { 120 int player_id) {
133 auto it = players_.find(PlayerIdentifier(observer, player_id)); 121 auto it = players_.find(PlayerIdentifier(observer, player_id));
134 if (it != players_.end()) 122 if (it != players_.end())
135 players_.erase(it); 123 players_.erase(it);
136 124
137 it = pepper_players_.find(PlayerIdentifier(observer, player_id));
138 if (it != pepper_players_.end())
139 pepper_players_.erase(it);
140
141 AbandonSystemAudioFocusIfNeeded(); 125 AbandonSystemAudioFocusIfNeeded();
142 } 126 }
143 127
144 void MediaSession::RemovePlayers(MediaSessionObserver* observer) { 128 void MediaSession::RemovePlayers(MediaSessionObserver* observer) {
145 for (auto it = players_.begin(); it != players_.end(); ) { 129 for (auto it = players_.begin(); it != players_.end();) {
146 if (it->observer == observer) 130 if (it->observer == observer)
147 players_.erase(it++); 131 players_.erase(it++);
148 else 132 else
149 ++it; 133 ++it;
150 } 134 }
151
152 for (auto it = pepper_players_.begin(); it != pepper_players_.end(); ) {
153 if (it->observer == observer)
154 pepper_players_.erase(it++);
155 else
156 ++it;
157 }
158 135
159 AbandonSystemAudioFocusIfNeeded(); 136 AbandonSystemAudioFocusIfNeeded();
160 } 137 }
161 138
162 void MediaSession::RecordSessionDuck() { 139 void MediaSession::RecordSessionDuck() {
163 uma_helper_.RecordSessionSuspended( 140 uma_helper_.RecordSessionSuspended(
164 MediaSessionSuspendedSource::SystemTransientDuck); 141 MediaSessionSuspendedSource::SystemTransientDuck);
165 } 142 }
166 143
167 void MediaSession::OnPlayerPaused(MediaSessionObserver* observer, 144 void MediaSession::OnPlayerPaused(MediaSessionObserver* observer,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 } 183 }
207 184
208 void MediaSession::Suspend(SuspendType suspend_type) { 185 void MediaSession::Suspend(SuspendType suspend_type) {
209 DCHECK(!IsSuspended()); 186 DCHECK(!IsSuspended());
210 187
211 OnSuspendInternal(suspend_type, State::SUSPENDED); 188 OnSuspendInternal(suspend_type, State::SUSPENDED);
212 } 189 }
213 190
214 void MediaSession::Stop(SuspendType suspend_type) { 191 void MediaSession::Stop(SuspendType suspend_type) {
215 DCHECK(audio_focus_state_ != State::INACTIVE); 192 DCHECK(audio_focus_state_ != State::INACTIVE);
193
216 DCHECK(suspend_type != SuspendType::CONTENT); 194 DCHECK(suspend_type != SuspendType::CONTENT);
217 DCHECK(!HasPepper());
218 195
219 // TODO(mlamouri): merge the logic between UI and SYSTEM. 196 // TODO(mlamouri): merge the logic between UI and SYSTEM.
220 if (suspend_type == SuspendType::SYSTEM) { 197 if (suspend_type == SuspendType::SYSTEM) {
221 OnSuspendInternal(suspend_type, State::INACTIVE); 198 OnSuspendInternal(suspend_type, State::INACTIVE);
222 return; 199 return;
223 } 200 }
224 201
225 if (audio_focus_state_ != State::SUSPENDED) 202 if (audio_focus_state_ != State::SUSPENDED)
226 OnSuspendInternal(suspend_type, State::SUSPENDED); 203 OnSuspendInternal(suspend_type, State::SUSPENDED);
227 204
228 DCHECK(audio_focus_state_ == State::SUSPENDED); 205 DCHECK(audio_focus_state_ == State::SUSPENDED);
229 players_.clear(); 206 players_.clear();
230
231 AbandonSystemAudioFocusIfNeeded(); 207 AbandonSystemAudioFocusIfNeeded();
232 } 208 }
233 209
234 void MediaSession::StartDucking() { 210 void MediaSession::StartDucking() {
235 if (is_ducking_) 211 if (is_ducking_)
236 return; 212 return;
237 is_ducking_ = true; 213 is_ducking_ = true;
238 UpdateVolumeMultiplier(); 214 UpdateVolumeMultiplier();
239 } 215 }
240 216
241 void MediaSession::StopDucking() { 217 void MediaSession::StopDucking() {
242 if (!is_ducking_) 218 if (!is_ducking_)
243 return; 219 return;
244 is_ducking_ = false; 220 is_ducking_ = false;
245 UpdateVolumeMultiplier(); 221 UpdateVolumeMultiplier();
246 } 222 }
247 223
248 void MediaSession::UpdateVolumeMultiplier() { 224 void MediaSession::UpdateVolumeMultiplier() {
249 for (const auto& it : players_) 225 for (const auto& it : players_)
250 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); 226 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
251 for (const auto& it : pepper_players_)
252 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
253 } 227 }
254 228
255 double MediaSession::GetVolumeMultiplier() const { 229 double MediaSession::GetVolumeMultiplier() const {
256 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier; 230 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier;
257 } 231 }
258 232
259 bool MediaSession::IsActive() const { 233 bool MediaSession::IsActive() const {
260 return audio_focus_state_ == State::ACTIVE; 234 return audio_focus_state_ == State::ACTIVE;
261 } 235 }
262 236
263 bool MediaSession::IsReallySuspended() const { 237 bool MediaSession::IsReallySuspended() const {
264 return audio_focus_state_ == State::SUSPENDED; 238 return audio_focus_state_ == State::SUSPENDED;
265 } 239 }
266 240
267 bool MediaSession::IsSuspended() const { 241 bool MediaSession::IsSuspended() const {
268 // TODO(mlamouri): should be == State::SUSPENDED. 242 // TODO(mlamouri): should be == State::SUSPENDED.
269 return audio_focus_state_ != State::ACTIVE; 243 return audio_focus_state_ != State::ACTIVE;
270 } 244 }
271 245
272 bool MediaSession::IsControllable() const { 246 bool MediaSession::IsControllable() const {
273 // Only media session having focus Gain can be controllable unless it is 247 // Only media session having focus Gain can be controllable unless it is
274 // inactive. 248 // inactive.
275 return audio_focus_state_ != State::INACTIVE && 249 return audio_focus_state_ != State::INACTIVE &&
276 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain; 250 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain;
277 } 251 }
278 252
279 bool MediaSession::HasPepper() const {
280 return !pepper_players_.empty();
281 }
282
283 std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription> 253 std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
284 MediaSession::RegisterMediaSessionStateChangedCallbackForTest( 254 MediaSession::RegisterMediaSessionStateChangedCallbackForTest(
285 const StateChangedCallback& cb) { 255 const StateChangedCallback& cb) {
286 return media_session_state_listeners_.Add(cb); 256 return media_session_state_listeners_.Add(cb);
287 } 257 }
288 258
289 void MediaSession::SetDelegateForTests( 259 void MediaSession::SetDelegateForTests(
290 std::unique_ptr<MediaSessionDelegate> delegate) { 260 std::unique_ptr<MediaSessionDelegate> delegate) {
291 delegate_ = std::move(delegate); 261 delegate_ = std::move(delegate);
292 } 262 }
293 263
294 bool MediaSession::IsActiveForTest() const { 264 bool MediaSession::IsActiveForTest() const {
295 return audio_focus_state_ == State::ACTIVE; 265 return audio_focus_state_ == State::ACTIVE;
296 } 266 }
297 267
268 AudioFocusManager::AudioFocusType MediaSession::audio_focus_type_for_test()
269 const {
270 return audio_focus_type_;
271 }
272
298 MediaSessionUmaHelper* MediaSession::uma_helper_for_test() { 273 MediaSessionUmaHelper* MediaSession::uma_helper_for_test() {
299 return &uma_helper_; 274 return &uma_helper_;
300 } 275 }
301 276
302 void MediaSession::RemoveAllPlayersForTest() { 277 void MediaSession::RemoveAllPlayersForTest() {
303 players_.clear(); 278 players_.clear();
304 AbandonSystemAudioFocusIfNeeded(); 279 AbandonSystemAudioFocusIfNeeded();
305 } 280 }
306 281
307 void MediaSession::OnSuspendInternal(SuspendType suspend_type, 282 void MediaSession::OnSuspendInternal(SuspendType suspend_type,
308 State new_state) { 283 State new_state) {
309 DCHECK(!HasPepper());
310
311 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); 284 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE);
312 // UI suspend cannot use State::INACTIVE. 285 // UI suspend cannot use State::INACTIVE.
313 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED); 286 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
314 287
315 if (audio_focus_state_ != State::ACTIVE) 288 if (audio_focus_state_ != State::ACTIVE)
316 return; 289 return;
317 290
318 switch (suspend_type) { 291 switch (suspend_type) {
319 case SuspendType::UI: 292 case SuspendType::UI:
320 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); 293 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI);
(...skipping 22 matching lines...) Expand all
343 suspend_type_ = suspend_type; 316 suspend_type_ = suspend_type;
344 317
345 if (suspend_type != SuspendType::CONTENT) { 318 if (suspend_type != SuspendType::CONTENT) {
346 // SuspendType::CONTENT happens when the suspend action came from 319 // SuspendType::CONTENT happens when the suspend action came from
347 // the page in which case the player is already paused. 320 // the page in which case the player is already paused.
348 // Otherwise, the players need to be paused. 321 // Otherwise, the players need to be paused.
349 for (const auto& it : players_) 322 for (const auto& it : players_)
350 it.observer->OnSuspend(it.player_id); 323 it.observer->OnSuspend(it.player_id);
351 } 324 }
352 325
353 for (const auto& it : pepper_players_)
354 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier);
355
356 UpdateWebContents(); 326 UpdateWebContents();
357 } 327 }
358 328
359 void MediaSession::OnResumeInternal(SuspendType suspend_type) { 329 void MediaSession::OnResumeInternal(SuspendType suspend_type) {
360 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) 330 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type)
361 return; 331 return;
362 332
363 SetAudioFocusState(State::ACTIVE); 333 SetAudioFocusState(State::ACTIVE);
364 334
365 for (const auto& it : players_) 335 for (const auto& it : players_)
366 it.observer->OnResume(it.player_id); 336 it.observer->OnResume(it.player_id);
367 337
368 for (const auto& it : pepper_players_)
369 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
370
371 UpdateWebContents(); 338 UpdateWebContents();
372 } 339 }
373 340
374 MediaSession::MediaSession(WebContents* web_contents) 341 MediaSession::MediaSession(WebContents* web_contents)
375 : WebContentsObserver(web_contents), 342 : WebContentsObserver(web_contents),
376 audio_focus_state_(State::INACTIVE), 343 audio_focus_state_(State::INACTIVE),
377 audio_focus_type_( 344 audio_focus_type_(
378 AudioFocusManager::AudioFocusType::GainTransientMayDuck), 345 AudioFocusManager::AudioFocusType::GainTransientMayDuck),
379 is_ducking_(false) {} 346 is_ducking_(false) {}
380 347
381 void MediaSession::Initialize() { 348 void MediaSession::Initialize() {
382 delegate_ = MediaSessionDelegate::Create(this); 349 delegate_ = MediaSessionDelegate::Create(this);
383 } 350 }
384 351
385 bool MediaSession::RequestSystemAudioFocus( 352 bool MediaSession::RequestSystemAudioFocus(
386 AudioFocusManager::AudioFocusType audio_focus_type) { 353 AudioFocusManager::AudioFocusType audio_focus_type) {
387 bool result = delegate_->RequestAudioFocus(audio_focus_type); 354 bool result = delegate_->RequestAudioFocus(audio_focus_type);
388 uma_helper_.RecordRequestAudioFocusResult(result); 355 uma_helper_.RecordRequestAudioFocusResult(result);
389
390 // MediaSession must change its state & audio focus type AFTER requesting
391 // audio focus.
392 SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE);
393 audio_focus_type_ = audio_focus_type;
394 return result; 356 return result;
395 } 357 }
396 358
397 void MediaSession::AbandonSystemAudioFocusIfNeeded() { 359 void MediaSession::AbandonSystemAudioFocusIfNeeded() {
398 if (audio_focus_state_ == State::INACTIVE || !players_.empty() || 360 if (audio_focus_state_ == State::INACTIVE || !players_.empty())
399 !pepper_players_.empty()) {
400 return; 361 return;
401 } 362
402 delegate_->AbandonAudioFocus(); 363 delegate_->AbandonAudioFocus();
403 364
404 SetAudioFocusState(State::INACTIVE); 365 SetAudioFocusState(State::INACTIVE);
405 UpdateWebContents(); 366 UpdateWebContents();
406 } 367 }
407 368
408 void MediaSession::UpdateWebContents() { 369 void MediaSession::UpdateWebContents() {
409 media_session_state_listeners_.Notify(audio_focus_state_); 370 media_session_state_listeners_.Notify(audio_focus_state_);
410 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); 371 static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged();
411 } 372 }
412 373
413 void MediaSession::SetAudioFocusState(State audio_focus_state) { 374 void MediaSession::SetAudioFocusState(State audio_focus_state) {
414 if (audio_focus_state == audio_focus_state_) 375 if (audio_focus_state == audio_focus_state_)
415 return; 376 return;
416 377
417 audio_focus_state_ = audio_focus_state; 378 audio_focus_state_ = audio_focus_state;
418 switch (audio_focus_state_) { 379 switch (audio_focus_state_) {
419 case State::ACTIVE: 380 case State::ACTIVE:
420 uma_helper_.OnSessionActive(); 381 uma_helper_.OnSessionActive();
421 break; 382 break;
422 case State::SUSPENDED: 383 case State::SUSPENDED:
423 uma_helper_.OnSessionSuspended(); 384 uma_helper_.OnSessionSuspended();
424 break; 385 break;
425 case State::INACTIVE: 386 case State::INACTIVE:
426 uma_helper_.OnSessionInactive(); 387 uma_helper_.OnSessionInactive();
427 break; 388 break;
428 } 389 }
429 } 390 }
430 391
431 bool MediaSession::AddPepperPlayer(MediaSessionObserver* observer,
432 int player_id) {
433 DCHECK(RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain));
434
435 pepper_players_.insert(PlayerIdentifier(observer, player_id));
436
437 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
438
439 return true;
440 }
441
442 } // namespace content 392 } // 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