OLD | NEW |
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/android/media_session.h" | 5 #include "content/browser/media/android/media_session.h" |
6 | 6 |
7 #include "base/android/context_utils.h" | 7 #include "base/android/context_utils.h" |
8 #include "base/android/jni_android.h" | 8 #include "base/android/jni_android.h" |
9 #include "content/browser/media/android/media_session_observer.h" | 9 #include "content/browser/media/android/media_session_observer.h" |
10 #include "content/browser/web_contents/web_contents_impl.h" | 10 #include "content/browser/web_contents/web_contents_impl.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 bool MediaSession::AddPlayer(MediaSessionObserver* observer, | 63 bool MediaSession::AddPlayer(MediaSessionObserver* observer, |
64 int player_id, | 64 int player_id, |
65 Type type) { | 65 Type type) { |
66 observer->OnSetVolumeMultiplier(player_id, volume_multiplier_); | |
67 | |
68 // If the audio focus is already granted and is of type Content, there is | 66 // If the audio focus is already granted and is of type Content, there is |
69 // nothing to do. If it is granted of type Transient the requested type is | 67 // nothing to do. If it is granted of type Transient the requested type is |
70 // also transient, there is also nothing to do. Otherwise, the session needs | 68 // also transient, there is also nothing to do. Otherwise, the session needs |
71 // to request audio focus again. | 69 // to request audio focus again. |
72 if (audio_focus_state_ == State::ACTIVE && | 70 if (audio_focus_state_ == State::ACTIVE && |
73 (audio_focus_type_ == Type::Content || audio_focus_type_ == type)) { | 71 (audio_focus_type_ == Type::Content || audio_focus_type_ == type)) { |
74 players_.insert(PlayerIdentifier(observer, player_id)); | 72 players_.insert(PlayerIdentifier(observer, player_id)); |
75 return true; | 73 } else { |
| 74 State old_audio_focus_state = audio_focus_state_; |
| 75 State audio_focus_state = RequestSystemAudioFocus(type) ? State::ACTIVE |
| 76 : State::INACTIVE; |
| 77 SetAudioFocusState(audio_focus_state); |
| 78 audio_focus_type_ = type; |
| 79 |
| 80 if (audio_focus_state_ != State::ACTIVE) |
| 81 return false; |
| 82 |
| 83 // The session should be reset if a player is starting while all players are |
| 84 // suspended. |
| 85 if (old_audio_focus_state != State::ACTIVE) |
| 86 players_.clear(); |
| 87 |
| 88 players_.insert(PlayerIdentifier(observer, player_id)); |
| 89 UpdateWebContents(); |
76 } | 90 } |
77 | 91 |
78 State old_audio_focus_state = audio_focus_state_; | 92 // Unmute audio for observers which may have started playing asynchronously in |
79 State audio_focus_state = RequestSystemAudioFocus(type) ? State::ACTIVE | 93 // a muted state while waiting for the focus approval. |
80 : State::INACTIVE; | 94 observer->OnSetVolumeMultiplier(player_id, volume_multiplier_); |
81 SetAudioFocusState(audio_focus_state); | |
82 audio_focus_type_ = type; | |
83 | |
84 if (audio_focus_state_ != State::ACTIVE) | |
85 return false; | |
86 | |
87 // The session should be reset if a player is starting while all players are | |
88 // suspended. | |
89 if (old_audio_focus_state != State::ACTIVE) | |
90 players_.clear(); | |
91 | |
92 players_.insert(PlayerIdentifier(observer, player_id)); | |
93 UpdateWebContents(); | |
94 | |
95 return true; | 95 return true; |
96 } | 96 } |
97 | 97 |
98 void MediaSession::RemovePlayer(MediaSessionObserver* observer, | 98 void MediaSession::RemovePlayer(MediaSessionObserver* observer, |
99 int player_id) { | 99 int player_id) { |
100 auto it = players_.find(PlayerIdentifier(observer, player_id)); | 100 auto it = players_.find(PlayerIdentifier(observer, player_id)); |
101 if (it != players_.end()) | 101 if (it != players_.end()) |
102 players_.erase(it); | 102 players_.erase(it); |
103 | 103 |
104 AbandonSystemAudioFocusIfNeeded(); | 104 AbandonSystemAudioFocusIfNeeded(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 // TODO(mlamouri): should be == State::SUSPENDED. | 198 // TODO(mlamouri): should be == State::SUSPENDED. |
199 return audio_focus_state_ != State::ACTIVE; | 199 return audio_focus_state_ != State::ACTIVE; |
200 } | 200 } |
201 | 201 |
202 bool MediaSession::IsControllable() const { | 202 bool MediaSession::IsControllable() const { |
203 // Only content type media session can be controllable unless it is inactive. | 203 // Only content type media session can be controllable unless it is inactive. |
204 return audio_focus_state_ != State::INACTIVE && | 204 return audio_focus_state_ != State::INACTIVE && |
205 audio_focus_type_ == Type::Content; | 205 audio_focus_type_ == Type::Content; |
206 } | 206 } |
207 | 207 |
208 void MediaSession::ResetJavaRefForTest() { | |
209 j_media_session_.Reset(); | |
210 } | |
211 | |
212 bool MediaSession::IsActiveForTest() const { | |
213 return audio_focus_state_ == State::ACTIVE; | |
214 } | |
215 | |
216 MediaSession::Type MediaSession::audio_focus_type_for_test() const { | |
217 return audio_focus_type_; | |
218 } | |
219 | |
220 MediaSessionUmaHelper* MediaSession::uma_helper_for_test() { | |
221 return &uma_helper_; | |
222 } | |
223 | |
224 void MediaSession::RemoveAllPlayersForTest() { | |
225 players_.clear(); | |
226 AbandonSystemAudioFocusIfNeeded(); | |
227 } | |
228 | |
229 void MediaSession::OnSuspendInternal(SuspendType type, State new_state) { | 208 void MediaSession::OnSuspendInternal(SuspendType type, State new_state) { |
230 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); | 209 DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE); |
231 // UI suspend cannot use State::INACTIVE. | 210 // UI suspend cannot use State::INACTIVE. |
232 DCHECK(type == SuspendType::SYSTEM || new_state == State::SUSPENDED); | 211 DCHECK(type == SuspendType::SYSTEM || new_state == State::SUSPENDED); |
233 | 212 |
234 switch (type) { | 213 switch (type) { |
235 case SuspendType::UI: | 214 case SuspendType::UI: |
236 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); | 215 uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI); |
237 break; | 216 break; |
238 case SuspendType::SYSTEM: | 217 case SuspendType::SYSTEM: |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 } | 261 } |
283 | 262 |
284 void MediaSession::OnSetVolumeMultiplierInternal(double volume_multiplier) { | 263 void MediaSession::OnSetVolumeMultiplierInternal(double volume_multiplier) { |
285 volume_multiplier_ = volume_multiplier; | 264 volume_multiplier_ = volume_multiplier; |
286 for (const auto& it : players_) | 265 for (const auto& it : players_) |
287 it.observer->OnSetVolumeMultiplier(it.player_id, volume_multiplier_); | 266 it.observer->OnSetVolumeMultiplier(it.player_id, volume_multiplier_); |
288 } | 267 } |
289 | 268 |
290 MediaSession::MediaSession(WebContents* web_contents) | 269 MediaSession::MediaSession(WebContents* web_contents) |
291 : WebContentsObserver(web_contents), | 270 : WebContentsObserver(web_contents), |
| 271 default_system_audio_focus_response_(true), |
292 audio_focus_state_(State::INACTIVE), | 272 audio_focus_state_(State::INACTIVE), |
293 audio_focus_type_(Type::Transient), | 273 audio_focus_type_(Type::Transient), |
294 volume_multiplier_(media::MediaPlayerAndroid::kDefaultVolumeMultiplier) { | 274 volume_multiplier_(media::MediaPlayerAndroid::kDefaultVolumeMultiplier) { |
295 } | 275 } |
296 | 276 |
297 void MediaSession::Initialize() { | 277 void MediaSession::Initialize() { |
298 JNIEnv* env = base::android::AttachCurrentThread(); | 278 JNIEnv* env = base::android::AttachCurrentThread(); |
299 DCHECK(env); | 279 DCHECK(env); |
300 j_media_session_.Reset(Java_MediaSession_createMediaSession( | 280 j_media_session_.Reset(Java_MediaSession_createMediaSession( |
301 env, | 281 env, |
302 base::android::GetApplicationContext(), | 282 base::android::GetApplicationContext(), |
303 reinterpret_cast<intptr_t>(this))); | 283 reinterpret_cast<intptr_t>(this))); |
304 } | 284 } |
305 | 285 |
306 bool MediaSession::RequestSystemAudioFocus(Type type) { | 286 bool MediaSession::RequestSystemAudioFocus(Type type) { |
307 // During tests, j_media_session_ might be null. | 287 // During tests, j_media_session_ might be null. |
308 if (j_media_session_.is_null()) | 288 if (j_media_session_.is_null()) |
309 return true; | 289 return default_system_audio_focus_response_; |
310 | 290 |
311 JNIEnv* env = base::android::AttachCurrentThread(); | 291 JNIEnv* env = base::android::AttachCurrentThread(); |
312 DCHECK(env); | 292 DCHECK(env); |
313 bool result = Java_MediaSession_requestAudioFocus(env, j_media_session_.obj(), | 293 bool result = Java_MediaSession_requestAudioFocus(env, j_media_session_.obj(), |
314 type == Type::Transient); | 294 type == Type::Transient); |
315 uma_helper_.RecordRequestAudioFocusResult(result); | 295 uma_helper_.RecordRequestAudioFocusResult(result); |
316 return result; | 296 return result; |
317 } | 297 } |
318 | 298 |
319 void MediaSession::AbandonSystemAudioFocusIfNeeded() { | 299 void MediaSession::AbandonSystemAudioFocusIfNeeded() { |
(...skipping 27 matching lines...) Expand all Loading... |
347 case State::SUSPENDED: | 327 case State::SUSPENDED: |
348 uma_helper_.OnSessionSuspended(); | 328 uma_helper_.OnSessionSuspended(); |
349 break; | 329 break; |
350 case State::INACTIVE: | 330 case State::INACTIVE: |
351 uma_helper_.OnSessionInactive(); | 331 uma_helper_.OnSessionInactive(); |
352 break; | 332 break; |
353 } | 333 } |
354 } | 334 } |
355 | 335 |
356 } // namespace content | 336 } // namespace content |
OLD | NEW |