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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java

Issue 2439483003: Link MediaSessionTabHelper with native MediaSession [CL is going to be split] (Closed)
Patch Set: addressed nits Created 4 years, 2 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
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 package org.chromium.chrome.browser.media.ui; 5 package org.chromium.chrome.browser.media.ui;
6 6
7 import android.app.Activity; 7 import android.app.Activity;
8 import android.content.Intent; 8 import android.content.Intent;
9 import android.graphics.Bitmap; 9 import android.graphics.Bitmap;
10 import android.media.AudioManager; 10 import android.media.AudioManager;
11 import android.text.TextUtils; 11 import android.text.TextUtils;
12 12
13 import org.chromium.base.ContextUtils; 13 import org.chromium.base.ContextUtils;
14 import org.chromium.base.Log; 14 import org.chromium.base.Log;
15 import org.chromium.base.VisibleForTesting;
15 import org.chromium.chrome.R; 16 import org.chromium.chrome.R;
16 import org.chromium.chrome.browser.metrics.MediaNotificationUma; 17 import org.chromium.chrome.browser.metrics.MediaNotificationUma;
17 import org.chromium.chrome.browser.metrics.MediaSessionUMA; 18 import org.chromium.chrome.browser.metrics.MediaSessionUMA;
18 import org.chromium.chrome.browser.tab.EmptyTabObserver; 19 import org.chromium.chrome.browser.tab.EmptyTabObserver;
19 import org.chromium.chrome.browser.tab.Tab; 20 import org.chromium.chrome.browser.tab.Tab;
20 import org.chromium.chrome.browser.tab.TabObserver; 21 import org.chromium.chrome.browser.tab.TabObserver;
21 import org.chromium.components.url_formatter.UrlFormatter; 22 import org.chromium.components.url_formatter.UrlFormatter;
23 import org.chromium.content_public.browser.MediaSessionDelegate;
22 import org.chromium.content_public.browser.WebContents; 24 import org.chromium.content_public.browser.WebContents;
23 import org.chromium.content_public.browser.WebContentsObserver;
24 import org.chromium.content_public.common.MediaMetadata; 25 import org.chromium.content_public.common.MediaMetadata;
25 import org.chromium.ui.base.WindowAndroid; 26 import org.chromium.ui.base.WindowAndroid;
26 27
27 import java.net.URI; 28 import java.net.URI;
28 import java.net.URISyntaxException; 29 import java.net.URISyntaxException;
30 import java.util.HashMap;
31
32 import javax.annotation.Nullable;
29 33
30 /** 34 /**
31 * A tab helper responsible for enabling/disabling media controls and passing 35 * A tab helper responsible for enabling/disabling media controls and passing
32 * media actions from the controls to the {@link org.chromium.content.browser.Me diaSession} 36 * media actions from the controls to the {@link org.chromium.content.browser.Me diaSession}
33 */ 37 */
34 public class MediaSessionTabHelper implements MediaImageCallback { 38 public class MediaSessionTabHelper implements MediaImageCallback {
35 private static final String TAG = "MediaSession"; 39 private static final String TAG = "MediaSession";
36 40
37 private static final String UNICODE_PLAY_CHARACTER = "\u25B6"; 41 private static final String UNICODE_PLAY_CHARACTER = "\u25B6";
38 private static final int MINIMAL_FAVICON_SIZE = 114; 42 private static final int MINIMAL_FAVICON_SIZE = 114;
39 43
40 private Tab mTab; 44 private Tab mTab;
41 private Bitmap mPageMediaImage = null; 45 private Bitmap mPageMediaImage = null;
42 private Bitmap mFavicon = null; 46 private Bitmap mFavicon = null;
43 private Bitmap mCurrentMediaImage = null; 47 private Bitmap mCurrentMediaImage = null;
44 private String mOrigin = null; 48 private String mOrigin = null;
45 private WebContents mWebContents; 49 private WebContents mWebContents;
46 private WebContentsObserver mWebContentsObserver; 50 private MediaSessionDelegate mMediaSessionDelegate;
47 private int mPreviousVolumeControlStream = AudioManager.USE_DEFAULT_STREAM_T YPE; 51 private int mPreviousVolumeControlStream = AudioManager.USE_DEFAULT_STREAM_T YPE;
48 private MediaNotificationInfo.Builder mNotificationInfoBuilder = null; 52 private MediaNotificationInfo.Builder mNotificationInfoBuilder = null;
49 // The fallback title if |mPageMetadata| is null or its title is empty. 53 // The fallback title if |mPageMetadata| is null or its title is empty.
50 private String mFallbackTitle = null; 54 private String mFallbackTitle = null;
51 // The metadata set by the page. 55 // The metadata set by the page.
52 private MediaMetadata mPageMetadata = null; 56 private MediaMetadata mPageMetadata = null;
53 // The currently showing metadata. 57 // The currently showing metadata.
54 private MediaMetadata mCurrentMetadata = null; 58 private MediaMetadata mCurrentMetadata = null;
55 private MediaImageManager mMediaImageManager = null; 59 private MediaImageManager mMediaImageManager = null;
56 60
61 private static HashMap<Tab, MediaSessionTabHelper> sTabToHelperMap =
whywhat 2016/10/20 22:56:53 having an extra method used just for testing is fi
Zhiqiang Zhang (Slow) 2016/10/21 13:43:52 Ahh, using SparseArray<> now, with TabId as key.
62 new HashMap<Tab, MediaSessionTabHelper>();
63
64 @VisibleForTesting
65 @Nullable
66 static MediaSessionTabHelper getHelperFromTabForTesting(Tab tab) {
67 return sTabToHelperMap.get(tab);
68 }
69
70 @VisibleForTesting
71 @Nullable
72 MediaSessionDelegate getMediaSessionDelegateForTesting() {
73 return mMediaSessionDelegate;
74 }
75
57 private MediaNotificationListener mControlsListener = new MediaNotificationL istener() { 76 private MediaNotificationListener mControlsListener = new MediaNotificationL istener() {
58 @Override 77 @Override
59 public void onPlay(int actionSource) { 78 public void onPlay(int actionSource) {
60 MediaSessionUMA 79 MediaSessionUMA
61 .recordPlay(MediaSessionTabHelper.convertMediaActionSourceTo UMA(actionSource)); 80 .recordPlay(MediaSessionTabHelper.convertMediaActionSourceTo UMA(actionSource));
62 81 if (mMediaSessionDelegate != null) mMediaSessionDelegate.resumeMedia Session();
63 mWebContents.resumeMediaSession();
64 } 82 }
65 83
66 @Override 84 @Override
67 public void onPause(int actionSource) { 85 public void onPause(int actionSource) {
68 MediaSessionUMA.recordPause( 86 MediaSessionUMA.recordPause(
69 MediaSessionTabHelper.convertMediaActionSourceToUMA(actionSo urce)); 87 MediaSessionTabHelper.convertMediaActionSourceToUMA(actionSo urce));
70 88 if (mMediaSessionDelegate != null) mMediaSessionDelegate.suspendMedi aSession();
71 mWebContents.suspendMediaSession();
72 } 89 }
73 90
74 @Override 91 @Override
75 public void onStop(int actionSource) { 92 public void onStop(int actionSource) {
76 MediaSessionUMA 93 MediaSessionUMA
77 .recordStop(MediaSessionTabHelper.convertMediaActionSourceTo UMA(actionSource)); 94 .recordStop(MediaSessionTabHelper.convertMediaActionSourceTo UMA(actionSource));
78 95 if (mMediaSessionDelegate != null) mMediaSessionDelegate.stopMediaSe ssion();
79 mWebContents.stopMediaSession();
80 } 96 }
81 }; 97 };
82 98
83 void hideNotification() { 99 void hideNotification() {
84 if (mTab == null) { 100 if (mTab == null) {
85 return; 101 return;
86 } 102 }
87 MediaNotificationManager.hide(mTab.getId(), R.id.media_playback_notifica tion); 103 MediaNotificationManager.hide(mTab.getId(), R.id.media_playback_notifica tion);
88 Activity activity = getActivityFromTab(mTab); 104 Activity activity = getActivityFromTab(mTab);
89 if (activity != null) { 105 if (activity != null) {
90 activity.setVolumeControlStream(mPreviousVolumeControlStream); 106 activity.setVolumeControlStream(mPreviousVolumeControlStream);
91 } 107 }
92 mNotificationInfoBuilder = null; 108 mNotificationInfoBuilder = null;
93 } 109 }
94 110
95 private WebContentsObserver createWebContentsObserver(WebContents webContent s) { 111 private MediaSessionDelegate createMediaSessionDelegate(WebContents webConte nts) {
96 return new WebContentsObserver(webContents) { 112 MediaSessionDelegate delegate = new MediaSessionDelegate() {
97 @Override 113 @Override
98 public void destroy() { 114 public void mediaSessionDisconnected() {
99 hideNotification(); 115 hideNotification();
100 super.destroy();
101 } 116 }
102 117
103 @Override 118 @Override
104 public void mediaSessionStateChanged(boolean isControllable, boolean isPaused) { 119 public void mediaSessionStateChanged(boolean isControllable, boolean isPaused) {
105 if (!isControllable) { 120 if (!isControllable) {
106 hideNotification(); 121 hideNotification();
107 return; 122 return;
108 } 123 }
109 124
110 Intent contentIntent = Tab.createBringTabToFrontIntent(mTab.getI d()); 125 Intent contentIntent = Tab.createBringTabToFrontIntent(mTab.getI d());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 @Override 158 @Override
144 public void mediaSessionMetadataChanged(MediaMetadata metadata) { 159 public void mediaSessionMetadataChanged(MediaMetadata metadata) {
145 mPageMetadata = metadata; 160 mPageMetadata = metadata;
146 if (mPageMetadata != null) { 161 if (mPageMetadata != null) {
147 mMediaImageManager.downloadImage(mPageMetadata.getArtwork(), 162 mMediaImageManager.downloadImage(mPageMetadata.getArtwork(),
148 MediaSessionTabHelper.this); 163 MediaSessionTabHelper.this);
149 } 164 }
150 updateNotificationMetadata(); 165 updateNotificationMetadata();
151 } 166 }
152 }; 167 };
168 webContents.addMediaSessionDelegate(delegate);
whywhat 2016/10/20 22:56:53 nit: why "add" can WC have more than one delegate?
Zhiqiang Zhang (Slow) 2016/10/21 13:43:52 Currently not. Using "set" might make content::Med
169 return delegate;
153 } 170 }
154 171
155 private void setWebContents(WebContents webContents) { 172 private void setWebContents(WebContents webContents) {
156 if (mWebContents == webContents) return; 173 if (mWebContents == webContents) return;
whywhat 2016/10/20 22:56:53 seems like we don't need mWebContents here, we cou
Zhiqiang Zhang (Slow) 2016/10/21 13:43:52 Maybe we can do it in a separate CL?
157 174
158 cleanupWebContents(); 175 cleanupWebContents();
159 mWebContents = webContents; 176 mWebContents = webContents;
160 if (mWebContents != null) mWebContentsObserver = createWebContentsObserv er(mWebContents); 177 if (mWebContents != null) {
178 if (mMediaSessionDelegate != null) mMediaSessionDelegate.disconnectM ediaSession();
whywhat 2016/10/20 22:56:53 this will always be null after cleanupWebContents.
Zhiqiang Zhang (Slow) 2016/10/21 13:43:52 Done.
179
180 mMediaSessionDelegate = createMediaSessionDelegate(mWebContents);
181 }
161 mMediaImageManager.setWebContents(mWebContents); 182 mMediaImageManager.setWebContents(mWebContents);
162 } 183 }
163 184
164 private void cleanupWebContents() { 185 private void cleanupWebContents() {
165 if (mWebContentsObserver != null) mWebContentsObserver.destroy(); 186 if (mMediaSessionDelegate != null) mMediaSessionDelegate.disconnectMedia Session();
166 mWebContentsObserver = null; 187 mMediaSessionDelegate = null;
167 mWebContents = null; 188 mWebContents = null;
168 } 189 }
169 190
170 private final TabObserver mTabObserver = new EmptyTabObserver() { 191 private final TabObserver mTabObserver = new EmptyTabObserver() {
171 @Override 192 @Override
172 public void onContentChanged(Tab tab) { 193 public void onContentChanged(Tab tab) {
173 assert tab == mTab; 194 assert tab == mTab;
174 setWebContents(tab.getWebContents()); 195 setWebContents(tab.getWebContents());
175 } 196 }
176 197
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 241
221 @Override 242 @Override
222 public void onDestroyed(Tab tab) { 243 public void onDestroyed(Tab tab) {
223 assert mTab == tab; 244 assert mTab == tab;
224 245
225 cleanupWebContents(); 246 cleanupWebContents();
226 247
227 hideNotification(); 248 hideNotification();
228 mTab.removeObserver(this); 249 mTab.removeObserver(this);
229 mTab = null; 250 mTab = null;
251 sTabToHelperMap.remove(tab);
230 } 252 }
231 }; 253 };
232 254
233 private MediaSessionTabHelper(Tab tab) { 255 private MediaSessionTabHelper(Tab tab) {
234 mTab = tab; 256 mTab = tab;
235 mTab.addObserver(mTabObserver); 257 mTab.addObserver(mTabObserver);
236 mMediaImageManager = new MediaImageManager( 258 mMediaImageManager = new MediaImageManager(
237 MINIMAL_FAVICON_SIZE, MediaNotificationManager.getMaximumLargeIconSi ze()); 259 MINIMAL_FAVICON_SIZE, MediaNotificationManager.getMaximumLargeIconSi ze());
238 if (mTab.getWebContents() != null) setWebContents(tab.getWebContents()); 260 if (mTab.getWebContents() != null) setWebContents(tab.getWebContents());
239 261
240 Activity activity = getActivityFromTab(mTab); 262 Activity activity = getActivityFromTab(mTab);
241 if (activity != null) { 263 if (activity != null) {
242 mPreviousVolumeControlStream = activity.getVolumeControlStream(); 264 mPreviousVolumeControlStream = activity.getVolumeControlStream();
243 } 265 }
266 sTabToHelperMap.put(tab, this);
244 } 267 }
245 268
246 /** 269 /**
247 * Creates the {@link MediaSessionTabHelper} for the given {@link Tab}. 270 * Creates the {@link MediaSessionTabHelper} for the given {@link Tab}.
248 * @param tab the tab to attach the helper to. 271 * @param tab the tab to attach the helper to.
249 */ 272 */
250 public static void createForTab(Tab tab) { 273 public static void createForTab(Tab tab) {
251 new MediaSessionTabHelper(tab); 274 new MediaSessionTabHelper(tab);
252 } 275 }
253 276
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 if (mNotificationInfoBuilder == null) return; 387 if (mNotificationInfoBuilder == null) return;
365 mNotificationInfoBuilder.setLargeIcon(mCurrentMediaImage); 388 mNotificationInfoBuilder.setLargeIcon(mCurrentMediaImage);
366 MediaNotificationManager.show( 389 MediaNotificationManager.show(
367 ContextUtils.getApplicationContext(), mNotificationInfoBuilder.b uild()); 390 ContextUtils.getApplicationContext(), mNotificationInfoBuilder.b uild());
368 } 391 }
369 392
370 private Bitmap getNotificationImage() { 393 private Bitmap getNotificationImage() {
371 return (mPageMediaImage != null) ? mPageMediaImage : mFavicon; 394 return (mPageMediaImage != null) ? mPageMediaImage : mFavicon;
372 } 395 }
373 } 396 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698