| 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 |