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

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

Issue 2123863004: ScreenCapture for Android phase1, part II (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments and rebase Created 4 years, 4 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; 5 package org.chromium.chrome.browser.media;
6 6
7 import android.app.Notification; 7 import android.app.Notification;
8 import android.app.NotificationManager; 8 import android.app.NotificationManager;
9 import android.app.PendingIntent; 9 import android.app.PendingIntent;
10 import android.app.Service; 10 import android.app.Service;
11 import android.content.Context; 11 import android.content.Context;
12 import android.content.Intent; 12 import android.content.Intent;
13 import android.content.SharedPreferences; 13 import android.content.SharedPreferences;
14 import android.os.IBinder; 14 import android.os.IBinder;
15 import android.support.v4.app.NotificationCompat; 15 import android.support.v4.app.NotificationCompat;
16 import android.util.SparseIntArray; 16 import android.util.SparseIntArray;
17 17
18 import org.chromium.base.ContextUtils; 18 import org.chromium.base.ContextUtils;
19 import org.chromium.base.Log; 19 import org.chromium.base.Log;
20 import org.chromium.chrome.R; 20 import org.chromium.chrome.R;
21 import org.chromium.chrome.browser.tab.Tab; 21 import org.chromium.chrome.browser.tab.Tab;
22 import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid;
22 23
23 import java.net.MalformedURLException; 24 import java.net.MalformedURLException;
24 import java.net.URL; 25 import java.net.URL;
25 import java.util.HashSet; 26 import java.util.HashSet;
26 import java.util.Iterator; 27 import java.util.Iterator;
27 import java.util.Set; 28 import java.util.Set;
28 29
29 /** 30 /**
30 * Service that creates/destroys the WebRTC notification when media capture star ts/stops. 31 * Service that creates/destroys the WebRTC notification when media capture star ts/stops.
31 */ 32 */
32 public class MediaCaptureNotificationService extends Service { 33 public class MediaCaptureNotificationService extends Service {
34 private static final String ACTION_MEDIA_CAPTURE_UPDATE =
35 "org.chromium.chrome.browser.media.SCREEN_CAPTURE_UPDATE";
36 private static final String ACTION_SCREEN_CAPTURE_STOP =
37 "org.chromium.chrome.browser.media.SCREEN_CAPTURE_STOP";
33 38
34 private static final String NOTIFICATION_NAMESPACE = "MediaCaptureNotificati onService"; 39 private static final String NOTIFICATION_NAMESPACE = "MediaCaptureNotificati onService";
35 40
36 private static final String NOTIFICATION_ID_EXTRA = "NotificationId"; 41 private static final String NOTIFICATION_ID_EXTRA = "NotificationId";
37 private static final String NOTIFICATION_MEDIA_TYPE_EXTRA = "NotificationMed iaType"; 42 private static final String NOTIFICATION_MEDIA_TYPE_EXTRA = "NotificationMed iaType";
38 private static final String NOTIFICATION_MEDIA_URL_EXTRA = "NotificationMedi aUrl"; 43 private static final String NOTIFICATION_MEDIA_URL_EXTRA = "NotificationMedi aUrl";
39 44
40 private static final String WEBRTC_NOTIFICATION_IDS = "WebRTCNotificationIds "; 45 private static final String WEBRTC_NOTIFICATION_IDS = "WebRTCNotificationIds ";
41 private static final String TAG = "MediaCapture"; 46 private static final String TAG = "MediaCapture";
42 47
43 private static final int MEDIATYPE_NO_MEDIA = 0; 48 private static final int MEDIATYPE_NO_MEDIA = 0;
44 private static final int MEDIATYPE_AUDIO_AND_VIDEO = 1; 49 private static final int MEDIATYPE_AUDIO_AND_VIDEO = 1;
45 private static final int MEDIATYPE_VIDEO_ONLY = 2; 50 private static final int MEDIATYPE_VIDEO_ONLY = 2;
46 private static final int MEDIATYPE_AUDIO_ONLY = 3; 51 private static final int MEDIATYPE_AUDIO_ONLY = 3;
52 private static final int MEDIATYPE_SCREEN_CAPTURE = 4;
47 53
48 private NotificationManager mNotificationManager; 54 private NotificationManager mNotificationManager;
49 private Context mContext; 55 private Context mContext;
50 private SharedPreferences mSharedPreferences; 56 private SharedPreferences mSharedPreferences;
51 private final SparseIntArray mNotifications = new SparseIntArray(); 57 private final SparseIntArray mNotifications = new SparseIntArray();
52 58
53 @Override 59 @Override
54 public void onCreate() { 60 public void onCreate() {
55 mContext = getApplicationContext(); 61 mContext = getApplicationContext();
56 mNotificationManager = (NotificationManager) mContext.getSystemService( 62 mNotificationManager = (NotificationManager) mContext.getSystemService(
(...skipping 19 matching lines...) Expand all
76 private boolean doesNotificationExist(int notificationId) { 82 private boolean doesNotificationExist(int notificationId) {
77 return mNotifications.indexOfKey(notificationId) >= 0; 83 return mNotifications.indexOfKey(notificationId) >= 0;
78 } 84 }
79 85
80 @Override 86 @Override
81 public int onStartCommand(Intent intent, int flags, int startId) { 87 public int onStartCommand(Intent intent, int flags, int startId) {
82 if (intent == null || intent.getExtras() == null) { 88 if (intent == null || intent.getExtras() == null) {
83 cancelPreviousWebRtcNotifications(); 89 cancelPreviousWebRtcNotifications();
84 stopSelf(); 90 stopSelf();
85 } else { 91 } else {
86 updateNotification( 92 String action = intent.getAction();
87 intent.getIntExtra(NOTIFICATION_ID_EXTRA, Tab.INVALID_TAB_ID ), 93 int notificationId = intent.getIntExtra(NOTIFICATION_ID_EXTRA, Tab.I NVALID_TAB_ID);
88 intent.getIntExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, MEDIATYPE_ NO_MEDIA), 94 int mediaType = intent.getIntExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, ME DIATYPE_NO_MEDIA);
89 intent.getStringExtra(NOTIFICATION_MEDIA_URL_EXTRA)); 95 String url = intent.getStringExtra(NOTIFICATION_MEDIA_URL_EXTRA);
96
97 switch (action) {
98 case ACTION_MEDIA_CAPTURE_UPDATE:
Ted C 2016/08/16 00:19:19 since we only have two actions, I think if (ACTI
braveyao 2016/08/16 23:05:49 Done.
99 updateNotification(notificationId, mediaType, url);
100 break;
101
102 case ACTION_SCREEN_CAPTURE_STOP:
103 // Notify native to stop screen capture when the STOP button in notification
104 // is clicked.
105 TabWebContentsDelegateAndroid.notifyStopped(notificationId);
106 break;
107
108 default:
109 break;
110 }
90 } 111 }
91 return super.onStartCommand(intent, flags, startId); 112 return super.onStartCommand(intent, flags, startId);
92 } 113 }
93 114
94 /** 115 /**
95 * Cancel all previously existing notifications. Essential while doing a cle an start (may be 116 * Cancel all previously existing notifications. Essential while doing a cle an start (may be
96 * after a browser crash which caused old notifications to exist). 117 * after a browser crash which caused old notifications to exist).
97 */ 118 */
98 private void cancelPreviousWebRtcNotifications() { 119 private void cancelPreviousWebRtcNotifications() {
99 Set<String> notificationIds = 120 Set<String> notificationIds =
(...skipping 15 matching lines...) Expand all
115 * @param mediaType Media type of the notification. 136 * @param mediaType Media type of the notification.
116 * @param url Url of the current webrtc call. 137 * @param url Url of the current webrtc call.
117 */ 138 */
118 private void updateNotification(int notificationId, int mediaType, String ur l) { 139 private void updateNotification(int notificationId, int mediaType, String ur l) {
119 if (doesNotificationExist(notificationId) 140 if (doesNotificationExist(notificationId)
120 && !doesNotificationNeedUpdate(notificationId, mediaType)) { 141 && !doesNotificationNeedUpdate(notificationId, mediaType)) {
121 return; 142 return;
122 } 143 }
123 destroyNotification(notificationId); 144 destroyNotification(notificationId);
124 if (mediaType != MEDIATYPE_NO_MEDIA) { 145 if (mediaType != MEDIATYPE_NO_MEDIA) {
125 createNotification(notificationId, mediaType, url); 146 createNotification(notificationId, mediaType, url, true);
Ted C 2016/08/16 00:19:19 this is only ever called once...and we always pass
braveyao 2016/08/16 23:05:49 Done. Once there was another action added, which i
126 } 147 }
127 if (mNotifications.size() == 0) stopSelf(); 148 if (mNotifications.size() == 0) stopSelf();
128 } 149 }
129 150
130 /** 151 /**
131 * Destroys the notification for the id notificationId. 152 * Destroys the notification for the id notificationId.
132 * @param notificationId Unique id of the notification. 153 * @param notificationId Unique id of the notification.
133 */ 154 */
134 private void destroyNotification(int notificationId) { 155 private void destroyNotification(int notificationId) {
135 if (doesNotificationExist(notificationId)) { 156 if (doesNotificationExist(notificationId)) {
136 mNotificationManager.cancel(NOTIFICATION_NAMESPACE, notificationId); 157 mNotificationManager.cancel(NOTIFICATION_NAMESPACE, notificationId);
137 mNotifications.delete(notificationId); 158 mNotifications.delete(notificationId);
138 updateSharedPreferencesEntry(notificationId, true); 159 updateSharedPreferencesEntry(notificationId, true);
139 } 160 }
140 } 161 }
141 162
142 /** 163 /**
143 * Creates a notification for the provided notificationId and mediaType. 164 * Creates a notification for the provided notificationId and mediaType.
144 * @param notificationId Unique id of the notification. 165 * @param notificationId Unique id of the notification.
145 * @param mediaType Media type of the notification. 166 * @param mediaType Media type of the notification.
146 * @param url Url of the current webrtc call. 167 * @param url Url of the current webrtc call.
147 */ 168 */
148 private void createNotification(int notificationId, int mediaType, String ur l) { 169 private void createNotification(
170 int notificationId, int mediaType, String url, boolean headsup) {
149 int notificationContentTextId = 0; 171 int notificationContentTextId = 0;
150 int notificationIconId = 0; 172 int notificationIconId = 0;
151 if (mediaType == MEDIATYPE_AUDIO_AND_VIDEO) { 173 if (mediaType == MEDIATYPE_AUDIO_AND_VIDEO) {
152 notificationContentTextId = R.string.video_audio_call_notification_t ext_2; 174 notificationContentTextId = R.string.video_audio_call_notification_t ext_2;
153 notificationIconId = R.drawable.webrtc_video; 175 notificationIconId = R.drawable.webrtc_video;
154 } else if (mediaType == MEDIATYPE_VIDEO_ONLY) { 176 } else if (mediaType == MEDIATYPE_VIDEO_ONLY) {
155 notificationContentTextId = R.string.video_call_notification_text_2; 177 notificationContentTextId = R.string.video_call_notification_text_2;
156 notificationIconId = R.drawable.webrtc_video; 178 notificationIconId = R.drawable.webrtc_video;
157 } else if (mediaType == MEDIATYPE_AUDIO_ONLY) { 179 } else if (mediaType == MEDIATYPE_AUDIO_ONLY) {
158 notificationContentTextId = R.string.audio_call_notification_text_2; 180 notificationContentTextId = R.string.audio_call_notification_text_2;
159 notificationIconId = R.drawable.webrtc_audio; 181 notificationIconId = R.drawable.webrtc_audio;
182 } else if (mediaType == MEDIATYPE_SCREEN_CAPTURE) {
183 notificationContentTextId = R.string.screen_capture_notification_tex t;
184 notificationIconId = R.drawable.webrtc_video;
160 } 185 }
161 186
162 NotificationCompat.Builder builder = new NotificationCompat.Builder(mCon text) 187 NotificationCompat.Builder builder = new NotificationCompat.Builder(mCon text)
163 .setAutoCancel(false) 188 .setAutoCancel(false)
164 .setOngoing(true) 189 .setOngoing(true)
165 .setContentTitle(mContext.getString(R.string.app_name)) 190 .setContentTitle(mContext.getString(R.string.app_name))
166 .setSmallIcon(notificationIconId) 191 .setSmallIcon(notificationIconId)
167 .setLocalOnly(true); 192 .setLocalOnly(true);
168 193
169 StringBuilder contentText = new StringBuilder( 194 StringBuilder contentText =
170 mContext.getResources().getString(notificationContentTextId)).ap pend('.'); 195 new StringBuilder(mContext.getResources().getString(notification ContentTextId, url))
Ted C 2016/08/16 00:19:19 While extra arguments are dropped in the underlyin
braveyao 2016/08/16 23:05:49 Done.
196 .append('.');
171 Intent tabIntent = Tab.createBringTabToFrontIntent(notificationId); 197 Intent tabIntent = Tab.createBringTabToFrontIntent(notificationId);
172 if (tabIntent != null) { 198 if (tabIntent != null) {
173 PendingIntent contentIntent = PendingIntent.getActivity( 199 PendingIntent contentIntent = PendingIntent.getActivity(
174 mContext, notificationId, tabIntent, 0); 200 mContext, notificationId, tabIntent, 0);
175 builder.setContentIntent(contentIntent); 201 builder.setContentIntent(contentIntent);
176 contentText.append( 202 if (mediaType == MEDIATYPE_SCREEN_CAPTURE) {
177 mContext.getResources().getString(R.string.media_notificatio n_link_text, url)); 203 // Add a "Stop" button to the screen capture notification. If ne cessary, turn the
204 // notification into a high priority one.
205 if (headsup) {
206 builder.setPriority(Notification.PRIORITY_HIGH);
207 builder.setVibrate(new long[0]);
Ted C 2016/08/16 00:19:19 we don't vibrate for any other notifications...see
braveyao 2016/08/16 23:05:49 We don't vibrate for screen share too. 'setVibrate
208 }
209 builder.addAction(R.drawable.ic_vidcontrol_stop, "Stop",
Ted C 2016/08/16 00:19:19 "Stop" should be translated...and we might already
braveyao 2016/08/16 23:05:49 Done.
210 buildPendingIntent(ACTION_SCREEN_CAPTURE_STOP, notificat ionId, mediaType,
Ted C 2016/08/16 00:19:19 again, let's not make this overly generic for now.
braveyao 2016/08/16 23:05:49 Done.
211 url));
Ted C 2016/08/16 00:19:19 clang formatting doesn't work perfectly in java...
braveyao 2016/08/16 23:05:49 Done.
212 } else {
213 contentText.append(mContext.getResources().getString(
214 R.string.media_notification_link_text, url));
215 }
178 } else { 216 } else {
179 contentText.append(" ").append(url); 217 contentText.append(" ").append(url);
180 } 218 }
181 builder.setContentText(contentText); 219 builder.setContentText(contentText);
182 220
183 Notification notification = new NotificationCompat.BigTextStyle(builder) 221 Notification notification = new NotificationCompat.BigTextStyle(builder)
184 .bigText(contentText).build(); 222 .bigText(contentText).build();
185 mNotificationManager.notify(NOTIFICATION_NAMESPACE, notificationId, noti fication); 223 mNotificationManager.notify(NOTIFICATION_NAMESPACE, notificationId, noti fication);
186 mNotifications.put(notificationId, mediaType); 224 mNotifications.put(notificationId, mediaType);
187 updateSharedPreferencesEntry(notificationId, false); 225 updateSharedPreferencesEntry(notificationId, false);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 } 258 }
221 259
222 @Override 260 @Override
223 public IBinder onBind(Intent intent) { 261 public IBinder onBind(Intent intent) {
224 return null; 262 return null;
225 } 263 }
226 264
227 /** 265 /**
228 * @param audio If audio is being captured. 266 * @param audio If audio is being captured.
229 * @param video If video is being captured. 267 * @param video If video is being captured.
268 * @param screen If screen is being captured.
230 * @return A constant identify what media is being captured. 269 * @return A constant identify what media is being captured.
231 */ 270 */
232 public static int getMediaType(boolean audio, boolean video) { 271 public static int getMediaType(boolean audio, boolean video, boolean screen) {
233 if (audio && video) { 272 if (screen) {
273 return MEDIATYPE_SCREEN_CAPTURE;
274 } else if (audio && video) {
234 return MEDIATYPE_AUDIO_AND_VIDEO; 275 return MEDIATYPE_AUDIO_AND_VIDEO;
235 } else if (audio) { 276 } else if (audio) {
236 return MEDIATYPE_AUDIO_ONLY; 277 return MEDIATYPE_AUDIO_ONLY;
237 } else if (video) { 278 } else if (video) {
238 return MEDIATYPE_VIDEO_ONLY; 279 return MEDIATYPE_VIDEO_ONLY;
239 } else { 280 } else {
240 return MEDIATYPE_NO_MEDIA; 281 return MEDIATYPE_NO_MEDIA;
241 } 282 }
242 } 283 }
243 284
(...skipping 13 matching lines...) Expand all
257 298
258 /** 299 /**
259 * Send an intent to MediaCaptureNotificationService to either create, updat e or destroy the 300 * Send an intent to MediaCaptureNotificationService to either create, updat e or destroy the
260 * notification identified by tabId. 301 * notification identified by tabId.
261 * @param tabId Unique notification id. 302 * @param tabId Unique notification id.
262 * @param audio If audio is being captured. 303 * @param audio If audio is being captured.
263 * @param video If video is being captured. 304 * @param video If video is being captured.
264 * @param fullUrl Url of the current webrtc call. 305 * @param fullUrl Url of the current webrtc call.
265 */ 306 */
266 public static void updateMediaNotificationForTab( 307 public static void updateMediaNotificationForTab(
267 Context context, int tabId, boolean audio, boolean video, String ful lUrl) { 308 Context context, int tabId, int mediaType, String fullUrl) {
Ted C 2016/08/16 00:19:19 update javadoc
braveyao 2016/08/16 23:05:49 Done.
268 int mediaType = getMediaType(audio, video);
269 if (!shouldStartService(context, mediaType, tabId)) return; 309 if (!shouldStartService(context, mediaType, tabId)) return;
270 Intent intent = new Intent(context, MediaCaptureNotificationService.clas s); 310 Intent intent = new Intent(context, MediaCaptureNotificationService.clas s);
311 intent.setAction(ACTION_MEDIA_CAPTURE_UPDATE);
271 intent.putExtra(NOTIFICATION_ID_EXTRA, tabId); 312 intent.putExtra(NOTIFICATION_ID_EXTRA, tabId);
272 String baseUrl = fullUrl; 313 String baseUrl = fullUrl;
273 try { 314 try {
274 URL url = new URL(fullUrl); 315 URL url = new URL(fullUrl);
275 baseUrl = url.getProtocol() + "://" + url.getHost(); 316 baseUrl = url.getProtocol() + "://" + url.getHost();
276 } catch (MalformedURLException e) { 317 } catch (MalformedURLException e) {
277 Log.w(TAG, "Error parsing the webrtc url, %s ", fullUrl); 318 Log.w(TAG, "Error parsing the webrtc url, %s ", fullUrl);
278 } 319 }
279 intent.putExtra(NOTIFICATION_MEDIA_URL_EXTRA, baseUrl); 320 intent.putExtra(NOTIFICATION_MEDIA_URL_EXTRA, baseUrl);
280 intent.putExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, mediaType); 321 intent.putExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, mediaType);
281 context.startService(intent); 322 context.startService(intent);
282 } 323 }
283 324
284 /** 325 /**
285 * Clear any previous media notifications. 326 * Clear any previous media notifications.
286 */ 327 */
287 public static void clearMediaNotifications(Context context) { 328 public static void clearMediaNotifications(Context context) {
288 SharedPreferences sharedPreferences = 329 SharedPreferences sharedPreferences =
289 ContextUtils.getAppSharedPreferences(); 330 ContextUtils.getAppSharedPreferences();
290 Set<String> notificationIds = 331 Set<String> notificationIds =
291 sharedPreferences.getStringSet(WEBRTC_NOTIFICATION_IDS, null); 332 sharedPreferences.getStringSet(WEBRTC_NOTIFICATION_IDS, null);
292 if (notificationIds == null || notificationIds.isEmpty()) return; 333 if (notificationIds == null || notificationIds.isEmpty()) return;
293 334
294 context.startService(new Intent(context, MediaCaptureNotificationService .class)); 335 context.startService(new Intent(context, MediaCaptureNotificationService .class));
295 } 336 }
337
338 /**
339 * Build PendingIntent for the actions of screen capture notification.
340 */
341 private PendingIntent buildPendingIntent(
342 String action, int notificationId, int mediaType, String url) {
343 Intent intent = new Intent(this, MediaCaptureNotificationService.class);
344 intent.setAction(action);
345 intent.putExtra(NOTIFICATION_ID_EXTRA, notificationId);
346 intent.putExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, mediaType);
347 intent.putExtra(NOTIFICATION_MEDIA_URL_EXTRA, url);
348 return PendingIntent.getService(
349 mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURR ENT);
350 }
296 } 351 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698