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

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

Issue 2475473002: Implement one-shot audio focus inside MediaSession (Closed)
Patch Set: fixed a case where removing the last one-shot player Created 4 years, 1 month 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_impl.h" 5 #include "content/browser/media/session/media_session_impl.h"
6 6
7 #include <algorithm>
7 #include "content/browser/media/session/audio_focus_delegate.h" 8 #include "content/browser/media/session/audio_focus_delegate.h"
8 #include "content/browser/media/session/media_session_player_observer.h" 9 #include "content/browser/media/session/media_session_player_observer.h"
9 #include "content/browser/media/session/media_session_service_impl.h" 10 #include "content/browser/media/session/media_session_service_impl.h"
10 #include "content/browser/web_contents/web_contents_impl.h" 11 #include "content/browser/web_contents/web_contents_impl.h"
11 #include "content/public/browser/media_session.h" 12 #include "content/public/browser/media_session.h"
12 #include "content/public/browser/media_session_observer.h" 13 #include "content/public/browser/media_session_observer.h"
13 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
14 #include "media/base/media_content_type.h" 15 #include "media/base/media_content_type.h"
15 16
16 #if defined(OS_ANDROID) 17 #if defined(OS_ANDROID)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 MediaSessionImpl* session = FromWebContents(web_contents); 60 MediaSessionImpl* session = FromWebContents(web_contents);
60 if (!session) { 61 if (!session) {
61 CreateForWebContents(web_contents); 62 CreateForWebContents(web_contents);
62 session = FromWebContents(web_contents); 63 session = FromWebContents(web_contents);
63 session->Initialize(); 64 session->Initialize();
64 } 65 }
65 return session; 66 return session;
66 } 67 }
67 68
68 MediaSessionImpl::~MediaSessionImpl() { 69 MediaSessionImpl::~MediaSessionImpl() {
69 DCHECK(players_.empty()); 70 DCHECK(normal_players_.empty());
71 DCHECK(pepper_players_.empty());
72 DCHECK(one_shot_players_.empty());
70 DCHECK(audio_focus_state_ == State::INACTIVE); 73 DCHECK(audio_focus_state_ == State::INACTIVE);
71 for (auto& observer : observers_) 74 for (auto& observer : observers_)
72 observer.MediaSessionDestroyed(); 75 observer.MediaSessionDestroyed();
73 } 76 }
74 77
75 void MediaSessionImpl::WebContentsDestroyed() { 78 void MediaSessionImpl::WebContentsDestroyed() {
76 // This should only work for tests. In production, all the players should have 79 // This should only work for tests. In production, all the players should have
77 // already been removed before WebContents is destroyed. 80 // already been removed before WebContents is destroyed.
78 81
79 // TODO(zqzhang): refactor MediaSessionImpl, maybe move the interface used to 82 // TODO(zqzhang): refactor MediaSessionImpl, maybe move the interface used to
80 // talk with AudioFocusManager out to a seperate class. The AudioFocusManager 83 // talk with AudioFocusManager out to a seperate class. The AudioFocusManager
81 // unit tests then could mock the interface and abandon audio focus when 84 // unit tests then could mock the interface and abandon audio focus when
82 // WebContents is destroyed. See https://crbug.com/651069 85 // WebContents is destroyed. See https://crbug.com/651069
83 players_.clear(); 86 normal_players_.clear();
84 pepper_players_.clear(); 87 pepper_players_.clear();
88 one_shot_players_.clear();
85 AbandonSystemAudioFocusIfNeeded(); 89 AbandonSystemAudioFocusIfNeeded();
86 } 90 }
87 91
88 void MediaSessionImpl::SetMediaSessionService( 92 void MediaSessionImpl::SetMediaSessionService(
89 MediaSessionServiceImpl* service) { 93 MediaSessionServiceImpl* service) {
90 service_ = service; 94 service_ = service;
91 } 95 }
92 96
93 void MediaSessionImpl::AddObserver(MediaSessionObserver* observer) { 97 void MediaSessionImpl::AddObserver(MediaSessionObserver* observer) {
94 observers_.AddObserver(observer); 98 observers_.AddObserver(observer);
95 } 99 }
96 100
97 void MediaSessionImpl::RemoveObserver(MediaSessionObserver* observer) { 101 void MediaSessionImpl::RemoveObserver(MediaSessionObserver* observer) {
98 observers_.RemoveObserver(observer); 102 observers_.RemoveObserver(observer);
99 } 103 }
100 104
101 void MediaSessionImpl::SetMetadata( 105 void MediaSessionImpl::SetMetadata(
102 const base::Optional<MediaMetadata>& metadata) { 106 const base::Optional<MediaMetadata>& metadata) {
103 metadata_ = metadata; 107 metadata_ = metadata;
104 for (auto& observer : observers_) 108 for (auto& observer : observers_)
105 observer.MediaSessionMetadataChanged(metadata); 109 observer.MediaSessionMetadataChanged(metadata);
106 } 110 }
107 111
108 bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, 112 bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
109 int player_id, 113 int player_id,
110 media::MediaContentType media_content_type) { 114 media::MediaContentType media_content_type) {
111 if (media_content_type == media::MediaContentType::Uncontrollable) 115 if (media_content_type == media::MediaContentType::OneShot)
112 return true; 116 return AddOneShotPlayer(observer, player_id);
113 if (media_content_type == media::MediaContentType::Pepper) 117 if (media_content_type == media::MediaContentType::Pepper)
114 return AddPepperPlayer(observer, player_id); 118 return AddPepperPlayer(observer, player_id);
115 119
116 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); 120 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
117 121
118 // Determine the audio focus type required for playing the new player.
119 // TODO(zqzhang): handle duckable and uncontrollable.
120 // See https://crbug.com/639277.
121 AudioFocusManager::AudioFocusType required_audio_focus_type; 122 AudioFocusManager::AudioFocusType required_audio_focus_type;
122 if (media_content_type == media::MediaContentType::Persistent) { 123 if (media_content_type == media::MediaContentType::Persistent) {
123 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain; 124 required_audio_focus_type = AudioFocusManager::AudioFocusType::Gain;
124 } else { 125 } else {
125 required_audio_focus_type = 126 required_audio_focus_type =
126 AudioFocusManager::AudioFocusType::GainTransientMayDuck; 127 AudioFocusManager::AudioFocusType::GainTransientMayDuck;
127 } 128 }
128 129
129 // If the audio focus is already granted and is of type Content, there is 130 // If the audio focus is already granted and is of type Content, there is
130 // nothing to do. If it is granted of type Transient the requested type is 131 // nothing to do. If it is granted of type Transient the requested type is
131 // also transient, there is also nothing to do. Otherwise, the session needs 132 // also transient, there is also nothing to do. Otherwise, the session needs
132 // to request audio focus again. 133 // to request audio focus again.
133 if (audio_focus_state_ == State::ACTIVE && 134 if (audio_focus_state_ == State::ACTIVE &&
134 (audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain || 135 (audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain ||
135 audio_focus_type_ == required_audio_focus_type)) { 136 audio_focus_type_ == required_audio_focus_type)) {
136 players_.insert(PlayerIdentifier(observer, player_id)); 137 normal_players_.insert(PlayerIdentifier(observer, player_id));
137 return true; 138 return true;
138 } 139 }
139 140
140 State old_audio_focus_state = audio_focus_state_; 141 State old_audio_focus_state = audio_focus_state_;
141 RequestSystemAudioFocus(required_audio_focus_type); 142 RequestSystemAudioFocus(required_audio_focus_type);
142 143
143 if (audio_focus_state_ != State::ACTIVE) 144 if (audio_focus_state_ != State::ACTIVE)
144 return false; 145 return false;
145 146
146 // The session should be reset if a player is starting while all players are 147 // The session should be reset if a player is starting while all players are
147 // suspended. 148 // suspended.
148 if (old_audio_focus_state != State::ACTIVE) 149 if (old_audio_focus_state != State::ACTIVE)
149 players_.clear(); 150 normal_players_.clear();
150 151
151 players_.insert(PlayerIdentifier(observer, player_id)); 152 normal_players_.insert(PlayerIdentifier(observer, player_id));
152 UpdateWebContents(); 153 NotifyAboutStateChange();
153 154
154 return true; 155 return true;
155 } 156 }
156 157
157 void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer, 158 void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer,
158 int player_id) { 159 int player_id) {
159 auto it = players_.find(PlayerIdentifier(observer, player_id)); 160 bool was_controllable = IsControllable();
160 if (it != players_.end())
161 players_.erase(it);
162 161
163 it = pepper_players_.find(PlayerIdentifier(observer, player_id)); 162 PlayerIdentifier identifier(observer, player_id);
163
164 auto it = normal_players_.find(identifier);
165 if (it != normal_players_.end())
166 normal_players_.erase(it);
167
168 it = pepper_players_.find(identifier);
164 if (it != pepper_players_.end()) 169 if (it != pepper_players_.end())
165 pepper_players_.erase(it); 170 pepper_players_.erase(it);
166 171
172 it = one_shot_players_.find(identifier);
173 if (it != one_shot_players_.end())
174 one_shot_players_.erase(it);
175
167 AbandonSystemAudioFocusIfNeeded(); 176 AbandonSystemAudioFocusIfNeeded();
177
178 // The session may become controllable after removing a one-shot player.
179 // However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
180 // about the state change.
181 if (!was_controllable && IsControllable())
182 NotifyAboutStateChange();
168 } 183 }
169 184
170 void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) { 185 void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
171 for (auto it = players_.begin(); it != players_.end();) { 186 bool was_controllable = IsControllable();
187
188 for (auto it = normal_players_.begin(); it != normal_players_.end();) {
172 if (it->observer == observer) 189 if (it->observer == observer)
173 players_.erase(it++); 190 normal_players_.erase(it++);
174 else 191 else
175 ++it; 192 ++it;
176 } 193 }
177 194
178 for (auto it = pepper_players_.begin(); it != pepper_players_.end();) { 195 for (auto it = pepper_players_.begin(); it != pepper_players_.end();) {
179 if (it->observer == observer) 196 if (it->observer == observer)
180 pepper_players_.erase(it++); 197 pepper_players_.erase(it++);
181 else 198 else
182 ++it; 199 ++it;
183 } 200 }
184 201
202 for (auto it = one_shot_players_.begin(); it != one_shot_players_.end();) {
203 if (it->observer == observer)
204 one_shot_players_.erase(it++);
205 else
206 ++it;
207 }
208
185 AbandonSystemAudioFocusIfNeeded(); 209 AbandonSystemAudioFocusIfNeeded();
210
211 // The session may become controllable after removing a one-shot player.
212 // However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
213 // about the state change.
214 if (!was_controllable && IsControllable())
215 NotifyAboutStateChange();
186 } 216 }
187 217
188 void MediaSessionImpl::RecordSessionDuck() { 218 void MediaSessionImpl::RecordSessionDuck() {
189 uma_helper_.RecordSessionSuspended( 219 uma_helper_.RecordSessionSuspended(
190 MediaSessionSuspendedSource::SystemTransientDuck); 220 MediaSessionSuspendedSource::SystemTransientDuck);
191 } 221 }
192 222
193 void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer, 223 void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer,
194 int player_id) { 224 int player_id) {
195 // If a playback is completed, BrowserMediaPlayerManager will call 225 // If a playback is completed, BrowserMediaPlayerManager will call
196 // OnPlayerPaused() after RemovePlayer(). This is a workaround. 226 // OnPlayerPaused() after RemovePlayer(). This is a workaround.
197 // Also, this method may be called when a player that is not added 227 // Also, this method may be called when a player that is not added
198 // to this session (e.g. a silent video) is paused. MediaSessionImpl 228 // to this session (e.g. a silent video) is paused. MediaSessionImpl
199 // should ignore the paused player for this case. 229 // should ignore the paused player for this case.
200 if (!players_.count(PlayerIdentifier(observer, player_id)) && 230 PlayerIdentifier identifier(observer, player_id);
201 !pepper_players_.count(PlayerIdentifier(observer, player_id))) { 231 if (!normal_players_.count(identifier) &&
232 !pepper_players_.count(identifier) &&
233 !one_shot_players_.count(identifier)) {
202 return; 234 return;
203 } 235 }
204 236
205 // If the player to be removed is a pepper player, or there is more than one 237 // If the player to be removed is a pepper player, or there is more than one
206 // observer, remove the paused one from the session. 238 // observer, remove the paused one from the session.
207 if (pepper_players_.count(PlayerIdentifier(observer, player_id)) || 239 if (pepper_players_.count(identifier) || normal_players_.size() != 1) {
208 players_.size() != 1) {
209 RemovePlayer(observer, player_id); 240 RemovePlayer(observer, player_id);
210 return; 241 return;
211 } 242 }
243
244 // If the player is a one-shot player, just remove it since it is not expected
245 // to resume a one-shot player via resuming MediaSession.
246 if (one_shot_players_.count(identifier)) {
247 RemovePlayer(observer, player_id);
248 return;
249 }
212 250
213 // Otherwise, suspend the session. 251 // Otherwise, suspend the session.
214 DCHECK(!IsSuspended()); 252 DCHECK(!IsSuspended());
215 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED); 253 OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
216 } 254 }
217 255
218 void MediaSessionImpl::Resume(SuspendType suspend_type) { 256 void MediaSessionImpl::Resume(SuspendType suspend_type) {
219 DCHECK(IsReallySuspended()); 257 DCHECK(IsReallySuspended());
220 258
221 // When the resume requests comes from another source than system, audio focus 259 // When the resume requests comes from another source than system, audio focus
(...skipping 27 matching lines...) Expand all
249 // TODO(mlamouri): merge the logic between UI and SYSTEM. 287 // TODO(mlamouri): merge the logic between UI and SYSTEM.
250 if (suspend_type == SuspendType::SYSTEM) { 288 if (suspend_type == SuspendType::SYSTEM) {
251 OnSuspendInternal(suspend_type, State::INACTIVE); 289 OnSuspendInternal(suspend_type, State::INACTIVE);
252 return; 290 return;
253 } 291 }
254 292
255 if (audio_focus_state_ != State::SUSPENDED) 293 if (audio_focus_state_ != State::SUSPENDED)
256 OnSuspendInternal(suspend_type, State::SUSPENDED); 294 OnSuspendInternal(suspend_type, State::SUSPENDED);
257 295
258 DCHECK(audio_focus_state_ == State::SUSPENDED); 296 DCHECK(audio_focus_state_ == State::SUSPENDED);
259 players_.clear(); 297 normal_players_.clear();
260 298
261 AbandonSystemAudioFocusIfNeeded(); 299 AbandonSystemAudioFocusIfNeeded();
262 } 300 }
263 301
264 void MediaSessionImpl::DidReceiveAction( 302 void MediaSessionImpl::DidReceiveAction(
265 blink::mojom::MediaSessionAction action) { 303 blink::mojom::MediaSessionAction action) {
266 if (service_) 304 if (service_)
267 service_->GetClient()->DidReceiveAction(action); 305 service_->GetClient()->DidReceiveAction(action);
268 } 306 }
269 307
(...skipping 17 matching lines...) Expand all
287 } 325 }
288 326
289 void MediaSessionImpl::StopDucking() { 327 void MediaSessionImpl::StopDucking() {
290 if (!is_ducking_) 328 if (!is_ducking_)
291 return; 329 return;
292 is_ducking_ = false; 330 is_ducking_ = false;
293 UpdateVolumeMultiplier(); 331 UpdateVolumeMultiplier();
294 } 332 }
295 333
296 void MediaSessionImpl::UpdateVolumeMultiplier() { 334 void MediaSessionImpl::UpdateVolumeMultiplier() {
297 for (const auto& it : players_) 335 for (const auto& it : normal_players_)
298 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); 336 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
299 for (const auto& it : pepper_players_) 337 for (const auto& it : pepper_players_)
300 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); 338 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
301 } 339 }
302 340
303 double MediaSessionImpl::GetVolumeMultiplier() const { 341 double MediaSessionImpl::GetVolumeMultiplier() const {
304 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier; 342 return is_ducking_ ? kDuckingVolumeMultiplier : kDefaultVolumeMultiplier;
305 } 343 }
306 344
307 bool MediaSessionImpl::IsActive() const { 345 bool MediaSessionImpl::IsActive() const {
308 return audio_focus_state_ == State::ACTIVE; 346 return audio_focus_state_ == State::ACTIVE;
309 } 347 }
310 348
311 bool MediaSessionImpl::IsReallySuspended() const { 349 bool MediaSessionImpl::IsReallySuspended() const {
312 return audio_focus_state_ == State::SUSPENDED; 350 return audio_focus_state_ == State::SUSPENDED;
313 } 351 }
314 352
315 bool MediaSessionImpl::IsSuspended() const { 353 bool MediaSessionImpl::IsSuspended() const {
316 // TODO(mlamouri): should be == State::SUSPENDED. 354 // TODO(mlamouri): should be == State::SUSPENDED.
317 return audio_focus_state_ != State::ACTIVE; 355 return audio_focus_state_ != State::ACTIVE;
318 } 356 }
319 357
320 bool MediaSessionImpl::IsControllable() const { 358 bool MediaSessionImpl::IsControllable() const {
321 // Only media session having focus Gain can be controllable unless it is 359 // Only media session having focus Gain can be controllable unless it is
322 // inactive. 360 // inactive. Also, the session will be uncontrollable if it contains one-shot
361 // players.
323 return audio_focus_state_ != State::INACTIVE && 362 return audio_focus_state_ != State::INACTIVE &&
324 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain; 363 audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain &&
364 one_shot_players_.empty();
325 } 365 }
326 366
327 bool MediaSessionImpl::HasPepper() const { 367 bool MediaSessionImpl::HasPepper() const {
328 return !pepper_players_.empty(); 368 return !pepper_players_.empty();
329 } 369 }
330 370
331 std::unique_ptr<base::CallbackList<void(MediaSessionImpl::State)>::Subscription> 371 std::unique_ptr<base::CallbackList<void(MediaSessionImpl::State)>::Subscription>
332 MediaSessionImpl::RegisterMediaSessionStateChangedCallbackForTest( 372 MediaSessionImpl::RegisterMediaSessionStateChangedCallbackForTest(
333 const StateChangedCallback& cb) { 373 const StateChangedCallback& cb) {
334 return media_session_state_listeners_.Add(cb); 374 return media_session_state_listeners_.Add(cb);
335 } 375 }
336 376
337 void MediaSessionImpl::SetDelegateForTests( 377 void MediaSessionImpl::SetDelegateForTests(
338 std::unique_ptr<AudioFocusDelegate> delegate) { 378 std::unique_ptr<AudioFocusDelegate> delegate) {
339 delegate_ = std::move(delegate); 379 delegate_ = std::move(delegate);
340 } 380 }
341 381
342 bool MediaSessionImpl::IsActiveForTest() const { 382 bool MediaSessionImpl::IsActiveForTest() const {
343 return audio_focus_state_ == State::ACTIVE; 383 return audio_focus_state_ == State::ACTIVE;
344 } 384 }
345 385
346 MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() { 386 MediaSessionUmaHelper* MediaSessionImpl::uma_helper_for_test() {
347 return &uma_helper_; 387 return &uma_helper_;
348 } 388 }
349 389
350 void MediaSessionImpl::RemoveAllPlayersForTest() { 390 void MediaSessionImpl::RemoveAllPlayersForTest() {
351 players_.clear(); 391 normal_players_.clear();
392 pepper_players_.clear();
393 one_shot_players_.clear();
352 AbandonSystemAudioFocusIfNeeded(); 394 AbandonSystemAudioFocusIfNeeded();
353 } 395 }
354 396
355 void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type, 397 void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
356 State new_state) { 398 State new_state) {
357 DCHECK(!HasPepper()); 399 DCHECK(!HasPepper());
358 400
359 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); 401 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE);
360 // UI suspend cannot use State::INACTIVE. 402 // UI suspend cannot use State::INACTIVE.
361 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED); 403 DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
362 404
405 if (!one_shot_players_.empty())
406 return;
407
363 if (audio_focus_state_ != State::ACTIVE) 408 if (audio_focus_state_ != State::ACTIVE)
364 return; 409 return;
365 410
366 switch (suspend_type) { 411 switch (suspend_type) {
367 case SuspendType::UI: 412 case SuspendType::UI:
368 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); 413 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI);
369 break; 414 break;
370 case SuspendType::SYSTEM: 415 case SuspendType::SYSTEM:
371 switch (new_state) { 416 switch (new_state) {
372 case State::SUSPENDED: 417 case State::SUSPENDED:
(...skipping 14 matching lines...) Expand all
387 break; 432 break;
388 } 433 }
389 434
390 SetAudioFocusState(new_state); 435 SetAudioFocusState(new_state);
391 suspend_type_ = suspend_type; 436 suspend_type_ = suspend_type;
392 437
393 if (suspend_type != SuspendType::CONTENT) { 438 if (suspend_type != SuspendType::CONTENT) {
394 // SuspendType::CONTENT happens when the suspend action came from 439 // SuspendType::CONTENT happens when the suspend action came from
395 // the page in which case the player is already paused. 440 // the page in which case the player is already paused.
396 // Otherwise, the players need to be paused. 441 // Otherwise, the players need to be paused.
397 for (const auto& it : players_) 442 for (const auto& it : normal_players_)
398 it.observer->OnSuspend(it.player_id); 443 it.observer->OnSuspend(it.player_id);
399 } 444 }
400 445
401 for (const auto& it : pepper_players_) 446 for (const auto& it : pepper_players_)
402 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier); 447 it.observer->OnSetVolumeMultiplier(it.player_id, kDuckingVolumeMultiplier);
403 448
404 UpdateWebContents(); 449 NotifyAboutStateChange();
405 } 450 }
406 451
407 void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) { 452 void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
408 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type) 453 if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type)
409 return; 454 return;
410 455
411 SetAudioFocusState(State::ACTIVE); 456 SetAudioFocusState(State::ACTIVE);
412 457
413 for (const auto& it : players_) 458 for (const auto& it : normal_players_)
414 it.observer->OnResume(it.player_id); 459 it.observer->OnResume(it.player_id);
415 460
416 for (const auto& it : pepper_players_) 461 for (const auto& it : pepper_players_)
417 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier()); 462 it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
418 463
419 UpdateWebContents(); 464 NotifyAboutStateChange();
420 } 465 }
421 466
422 MediaSessionImpl::MediaSessionImpl(WebContents* web_contents) 467 MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
423 : WebContentsObserver(web_contents), 468 : WebContentsObserver(web_contents),
424 audio_focus_state_(State::INACTIVE), 469 audio_focus_state_(State::INACTIVE),
425 audio_focus_type_( 470 audio_focus_type_(
426 AudioFocusManager::AudioFocusType::GainTransientMayDuck), 471 AudioFocusManager::AudioFocusType::GainTransientMayDuck),
427 is_ducking_(false), 472 is_ducking_(false),
428 service_(nullptr) { 473 service_(nullptr) {
429 #if defined(OS_ANDROID) 474 #if defined(OS_ANDROID)
(...skipping 11 matching lines...) Expand all
441 uma_helper_.RecordRequestAudioFocusResult(result); 486 uma_helper_.RecordRequestAudioFocusResult(result);
442 487
443 // MediaSessionImpl must change its state & audio focus type AFTER requesting 488 // MediaSessionImpl must change its state & audio focus type AFTER requesting
444 // audio focus. 489 // audio focus.
445 SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE); 490 SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE);
446 audio_focus_type_ = audio_focus_type; 491 audio_focus_type_ = audio_focus_type;
447 return result; 492 return result;
448 } 493 }
449 494
450 void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() { 495 void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
451 if (audio_focus_state_ == State::INACTIVE || !players_.empty() || 496 if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
452 !pepper_players_.empty()) { 497 !pepper_players_.empty() || !one_shot_players_.empty()) {
453 return; 498 return;
454 } 499 }
455 delegate_->AbandonAudioFocus(); 500 delegate_->AbandonAudioFocus();
456 501
457 SetAudioFocusState(State::INACTIVE); 502 SetAudioFocusState(State::INACTIVE);
458 UpdateWebContents(); 503 NotifyAboutStateChange();
459 } 504 }
460 505
461 void MediaSessionImpl::UpdateWebContents() { 506 void MediaSessionImpl::NotifyAboutStateChange() {
462 media_session_state_listeners_.Notify(audio_focus_state_); 507 media_session_state_listeners_.Notify(audio_focus_state_);
463 for (auto& observer : observers_) 508 for (auto& observer : observers_)
464 observer.MediaSessionStateChanged(IsControllable(), IsSuspended()); 509 observer.MediaSessionStateChanged(IsControllable(), IsSuspended());
465 } 510 }
466 511
467 void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) { 512 void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) {
468 if (audio_focus_state == audio_focus_state_) 513 if (audio_focus_state == audio_focus_state_)
469 return; 514 return;
470 515
471 audio_focus_state_ = audio_focus_state; 516 audio_focus_state_ = audio_focus_state;
(...skipping 13 matching lines...) Expand all
485 bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer, 530 bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
486 int player_id) { 531 int player_id) {
487 bool success = 532 bool success =
488 RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain); 533 RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain);
489 DCHECK(success); 534 DCHECK(success);
490 535
491 pepper_players_.insert(PlayerIdentifier(observer, player_id)); 536 pepper_players_.insert(PlayerIdentifier(observer, player_id));
492 537
493 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); 538 observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
494 539
540 NotifyAboutStateChange();
541 return success;
542 }
543
544 bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer,
545 int player_id) {
546 if (!RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain))
547 return false;
548
549 one_shot_players_.insert(PlayerIdentifier(observer, player_id));
550 NotifyAboutStateChange();
551
495 return true; 552 return true;
496 } 553 }
497 554
498 } // namespace content 555 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/session/media_session_impl.h ('k') | content/browser/media/session/media_session_impl_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698