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

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

Issue 1110833004: Move audio focus control from media/ to content/ and make it per WebContents. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/media/android/media_session.h"
6
7 #include "base/android/jni_android.h"
8 #include "content/browser/media/android/media_session_observer.h"
9 #include "jni/MediaSession_jni.h"
10
11 namespace content {
12
13 DEFINE_WEB_CONTENTS_USER_DATA_KEY(MediaSession);
14
15 MediaSession::PlayerIdentifier::PlayerIdentifier(MediaSessionObserver* observer,
16 int player_id)
17 : observer(observer),
18 player_id(player_id) {
19 }
20
21 bool MediaSession::PlayerIdentifier::operator==(
22 const PlayerIdentifier& other) const {
23 return this->observer == other.observer && this->player_id == other.player_id;
24 }
25
26 size_t MediaSession::PlayerIdentifier::Hash::operator()(
27 const PlayerIdentifier& player_identifier) const {
28 size_t hash = BASE_HASH_NAMESPACE::hash<MediaSessionObserver*>()(
29 player_identifier.observer);
30 hash += BASE_HASH_NAMESPACE::hash<int>()(player_identifier.player_id);
31 return hash;
32 }
33
34 // static
35 bool content::MediaSession::RegisterMediaSession(JNIEnv* env) {
36 return RegisterNativesImpl(env);
37 }
38
39 // static
40 MediaSession* MediaSession::Get(WebContents* web_contents) {
41 MediaSession* session = FromWebContents(web_contents);
42 if (!session) {
43 CreateForWebContents(web_contents);
44 session = FromWebContents(web_contents);
45 session->Initialize();
46 }
47 return session;
48 }
49
50 MediaSession::~MediaSession() {
51 DCHECK(players_.empty());
52 DCHECK(audio_focus_state_ == State::Suspended);
53 }
54
55 bool MediaSession::AddPlayer(MediaSessionObserver* observer,
56 int player_id,
57 Type type) {
58 // If the audio focus is already granted and is of type Content, there is
59 // nothing to do. If it is granted of type Transient the requested type is
60 // also transient, there is also nothing to do. Otherwise, the session needs
61 // to request audio focus again.
62 if (audio_focus_state_ == State::Active &&
63 (audio_focus_type_ == Type::Content || audio_focus_type_ == type)) {
64 players_.insert(PlayerIdentifier(observer, player_id));
65 return true;
66 }
67
68 State old_audio_focus_state = audio_focus_state_;
69 audio_focus_state_ = RequestSystemAudioFocus(type) ? State::Active
70 : State::Suspended;
71 audio_focus_type_ = type;
72
73 if (audio_focus_state_ != State::Active)
74 return false;
75
76 // The session should be reset if a player is starting while all players are
77 // suspended.
78 if (old_audio_focus_state != State::Active)
79 players_.clear();
80
81 players_.insert(PlayerIdentifier(observer, player_id));
82
83 return true;
84 }
85
86 void MediaSession::RemovePlayer(MediaSessionObserver* observer,
87 int player_id) {
88 auto it = players_.find(PlayerIdentifier(observer, player_id));
89 if (it != players_.end())
90 players_.erase(it);
91
92 AbandonSystemAudioFocusIfNeeded();
93 }
94
95 void MediaSession::RemovePlayers(MediaSessionObserver* observer) {
96 for (auto it = players_.begin(); it != players_.end();) {
97 if (it->observer == observer)
98 players_.erase(it++);
99 else
100 ++it;
101 }
102
103 AbandonSystemAudioFocusIfNeeded();
104 }
105
106 void MediaSession::OnSuspend(JNIEnv* env, jobject obj, jboolean temporary) {
107 OnSuspend(temporary);
108 }
109
110 void MediaSession::OnResume(JNIEnv* env, jobject obj) {
111 OnResume();
112 }
113
114 void MediaSession::ResetJavaRefForTest() {
115 j_media_session_.Reset();
116 }
117
118 bool MediaSession::IsActiveForTest() const {
119 return audio_focus_state_ == State::Active;
120 }
121
122 MediaSession::Type MediaSession::audio_focus_type_for_test() const {
123 return audio_focus_type_;
124 }
125
126 void MediaSession::OnSuspend(bool temporary) {
127 if (temporary)
128 audio_focus_state_ = State::TemporarilySuspended;
129 else
130 audio_focus_state_ = State::Suspended;
131
132 for (const auto& it : players_)
133 it.observer->OnSuspend(it.player_id);
134 }
135
136 void MediaSession::OnResume() {
137 audio_focus_state_ = State::Active;
138
139 for (const auto& it : players_)
140 it.observer->OnResume(it.player_id);
141 }
142
143 MediaSession::MediaSession(WebContents* web_contents)
144 : WebContentsObserver(web_contents),
145 audio_focus_state_(State::Suspended),
146 audio_focus_type_(Type::Transient) {
147 }
148
149 void MediaSession::Initialize() {
150 JNIEnv* env = base::android::AttachCurrentThread();
151 DCHECK(env);
152 j_media_session_.Reset(Java_MediaSession_createMediaSession(
153 env,
154 base::android::GetApplicationContext(),
155 reinterpret_cast<intptr_t>(this)));
156 }
157
158 bool MediaSession::RequestSystemAudioFocus(Type type) {
159 // During tests, j_media_session_ might be null.
160 if (j_media_session_.is_null())
161 return true;
162
163 JNIEnv* env = base::android::AttachCurrentThread();
164 DCHECK(env);
165 return Java_MediaSession_requestAudioFocus(env, j_media_session_.obj(),
166 type == Type::Transient);
167 }
168
169 void MediaSession::AbandonSystemAudioFocusIfNeeded() {
170 if (audio_focus_state_ == State::Suspended || !players_.empty())
171 return;
172
173 // During tests, j_media_session_ might be null.
174 if (!j_media_session_.is_null()) {
175 JNIEnv* env = base::android::AttachCurrentThread();
176 DCHECK(env);
177 Java_MediaSession_abandonAudioFocus(env, j_media_session_.obj());
178 }
179
180 audio_focus_state_ = State::Suspended;
181 }
182
183 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/android/media_session.h ('k') | content/browser/media/android/media_session_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698