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

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

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