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

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: rebase to #412340(Aug16) 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
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 if (ACTION_MEDIA_CAPTURE_UPDATE.equals(action)) {
98 updateNotification(notificationId, mediaType, url);
99 } else if (ACTION_SCREEN_CAPTURE_STOP.equals(action)) {
100 // Notify native to stop screen capture when the STOP button in notification
101 // is clicked.
102 TabWebContentsDelegateAndroid.notifyStopped(notificationId);
103 }
90 } 104 }
91 return super.onStartCommand(intent, flags, startId); 105 return super.onStartCommand(intent, flags, startId);
92 } 106 }
93 107
94 /** 108 /**
95 * Cancel all previously existing notifications. Essential while doing a cle an start (may be 109 * 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). 110 * after a browser crash which caused old notifications to exist).
97 */ 111 */
98 private void cancelPreviousWebRtcNotifications() { 112 private void cancelPreviousWebRtcNotifications() {
99 Set<String> notificationIds = 113 Set<String> notificationIds =
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 } 153 }
140 } 154 }
141 155
142 /** 156 /**
143 * Creates a notification for the provided notificationId and mediaType. 157 * Creates a notification for the provided notificationId and mediaType.
144 * @param notificationId Unique id of the notification. 158 * @param notificationId Unique id of the notification.
145 * @param mediaType Media type of the notification. 159 * @param mediaType Media type of the notification.
146 * @param url Url of the current webrtc call. 160 * @param url Url of the current webrtc call.
147 */ 161 */
148 private void createNotification(int notificationId, int mediaType, String ur l) { 162 private void createNotification(int notificationId, int mediaType, String ur l) {
149 int notificationContentTextId = 0;
150 int notificationIconId = 0;
151 if (mediaType == MEDIATYPE_AUDIO_AND_VIDEO) {
152 notificationContentTextId = R.string.video_audio_call_notification_t ext_2;
153 notificationIconId = R.drawable.webrtc_video;
154 } else if (mediaType == MEDIATYPE_VIDEO_ONLY) {
155 notificationContentTextId = R.string.video_call_notification_text_2;
156 notificationIconId = R.drawable.webrtc_video;
157 } else if (mediaType == MEDIATYPE_AUDIO_ONLY) {
158 notificationContentTextId = R.string.audio_call_notification_text_2;
159 notificationIconId = R.drawable.webrtc_audio;
160 }
161
162 NotificationCompat.Builder builder = new NotificationCompat.Builder(mCon text) 163 NotificationCompat.Builder builder = new NotificationCompat.Builder(mCon text)
163 .setAutoCancel(false) 164 .setAutoCancel(false)
164 .setOngoing(true) 165 .setOngoing(true)
165 .setContentTitle(mContext.getString(R.string.app_name)) 166 .setContentTitle(mContext.getString(R.string.app_name))
166 .setSmallIcon(notificationIconId) 167 .setSmallIcon(getNotificationIconId(mediaType))
167 .setLocalOnly(true); 168 .setLocalOnly(true);
168 169
169 StringBuilder contentText = new StringBuilder( 170 StringBuilder contentText = getNotificationContext(mediaType, url);
Ted C 2016/08/18 03:55:02 let's have this just return the String w/o the . a
braveyao 2016/08/18 18:16:51 Done.
170 mContext.getResources().getString(notificationContentTextId)).ap pend('.');
171 Intent tabIntent = Tab.createBringTabToFrontIntent(notificationId); 171 Intent tabIntent = Tab.createBringTabToFrontIntent(notificationId);
172 if (tabIntent != null) { 172 if (tabIntent != null) {
173 PendingIntent contentIntent = PendingIntent.getActivity( 173 PendingIntent contentIntent = PendingIntent.getActivity(
174 mContext, notificationId, tabIntent, 0); 174 mContext, notificationId, tabIntent, 0);
175 builder.setContentIntent(contentIntent); 175 builder.setContentIntent(contentIntent);
176 contentText.append( 176 if (mediaType == MEDIATYPE_SCREEN_CAPTURE) {
177 mContext.getResources().getString(R.string.media_notificatio n_link_text, url)); 177 // Add a "Stop" button to the screen capture notification and tu rn the notification
178 // into a high priority one.
179 builder.setPriority(Notification.PRIORITY_HIGH);
180 builder.setVibrate(new long[0]);
181 builder.addAction(R.drawable.ic_vidcontrol_stop,
182 mContext.getResources().getString(R.string.accessibility _stop),
183 buildStopCapturePendingIntent(notificationId));
184 } else {
185 contentText.append(mContext.getResources().getString(
186 R.string.media_notification_link_text, url));
187 }
178 } else { 188 } else {
179 contentText.append(" ").append(url); 189 contentText.append(" ").append(url);
180 } 190 }
181 builder.setContentText(contentText); 191 builder.setContentText(contentText);
182 192
183 Notification notification = new NotificationCompat.BigTextStyle(builder) 193 Notification notification = new NotificationCompat.BigTextStyle(builder)
184 .bigText(contentText).build(); 194 .bigText(contentText).build();
185 mNotificationManager.notify(NOTIFICATION_NAMESPACE, notificationId, noti fication); 195 mNotificationManager.notify(NOTIFICATION_NAMESPACE, notificationId, noti fication);
186 mNotifications.put(notificationId, mediaType); 196 mNotifications.put(notificationId, mediaType);
187 updateSharedPreferencesEntry(notificationId, false); 197 updateSharedPreferencesEntry(notificationId, false);
188 } 198 }
189 199
190 /** 200 /**
201 * Builds notification content text for the provided mediaType and url.
202 * @param mediaType Media type of the notification.
203 * @param url Url of the current webrtc call.
204 * @return A string builder initialized to the contents of the specified str ing.
205 */
206 private StringBuilder getNotificationContext(int mediaType, String url) {
Ted C 2016/08/18 03:55:01 I'd call this getNotificationTextContent. Context
braveyao 2016/08/18 18:16:51 Done.
207 int notificationContentTextId = 0;
208 if (mediaType == MEDIATYPE_AUDIO_AND_VIDEO) {
209 notificationContentTextId = R.string.video_audio_call_notification_t ext_2;
210 } else if (mediaType == MEDIATYPE_VIDEO_ONLY) {
211 notificationContentTextId = R.string.video_call_notification_text_2;
212 } else if (mediaType == MEDIATYPE_AUDIO_ONLY) {
213 notificationContentTextId = R.string.audio_call_notification_text_2;
214 } else if (mediaType == MEDIATYPE_SCREEN_CAPTURE) {
215 notificationContentTextId = R.string.screen_capture_notification_tex t;
216 }
217
218 StringBuilder contentText =
219 new StringBuilder(mContext.getResources().getString(notification ContentTextId, url))
Ted C 2016/08/18 03:55:01 I think I'd prefer a check at the top for MEDIATYP
braveyao 2016/08/18 18:16:51 Done.
220 .append('.');
221 return contentText;
222 }
223
224 /**
225 * @param mediaType Media type of the notification.
226 * @return An icon id of the provided mediaType.
227 */
228 private int getNotificationIconId(int mediaType) {
229 int notificationIconId = 0;
230 if (mediaType == MEDIATYPE_AUDIO_AND_VIDEO) {
231 notificationIconId = R.drawable.webrtc_video;
232 } else if (mediaType == MEDIATYPE_VIDEO_ONLY) {
233 notificationIconId = R.drawable.webrtc_video;
234 } else if (mediaType == MEDIATYPE_AUDIO_ONLY) {
235 notificationIconId = R.drawable.webrtc_audio;
236 } else if (mediaType == MEDIATYPE_SCREEN_CAPTURE) {
237 notificationIconId = R.drawable.webrtc_video;
238 }
239 return notificationIconId;
240 }
241
242 /**
191 * Update shared preferences entry with ids of the visible notifications. 243 * Update shared preferences entry with ids of the visible notifications.
192 * @param notificationId Id of the notification. 244 * @param notificationId Id of the notification.
193 * @param remove Boolean describing if the notification was added or removed . 245 * @param remove Boolean describing if the notification was added or removed .
194 */ 246 */
195 private void updateSharedPreferencesEntry(int notificationId, boolean remove ) { 247 private void updateSharedPreferencesEntry(int notificationId, boolean remove ) {
196 Set<String> notificationIds = 248 Set<String> notificationIds =
197 new HashSet<String>(mSharedPreferences.getStringSet(WEBRTC_NOTIF ICATION_IDS, 249 new HashSet<String>(mSharedPreferences.getStringSet(WEBRTC_NOTIF ICATION_IDS,
198 new HashSet<String>())); 250 new HashSet<String>()));
199 if (remove && !notificationIds.isEmpty() 251 if (remove && !notificationIds.isEmpty()
200 && notificationIds.contains(String.valueOf(notificationId))) { 252 && notificationIds.contains(String.valueOf(notificationId))) {
(...skipping 19 matching lines...) Expand all
220 } 272 }
221 273
222 @Override 274 @Override
223 public IBinder onBind(Intent intent) { 275 public IBinder onBind(Intent intent) {
224 return null; 276 return null;
225 } 277 }
226 278
227 /** 279 /**
228 * @param audio If audio is being captured. 280 * @param audio If audio is being captured.
229 * @param video If video is being captured. 281 * @param video If video is being captured.
282 * @param screen If screen is being captured.
230 * @return A constant identify what media is being captured. 283 * @return A constant identify what media is being captured.
231 */ 284 */
232 public static int getMediaType(boolean audio, boolean video) { 285 public static int getMediaType(boolean audio, boolean video, boolean screen) {
233 if (audio && video) { 286 if (screen) {
287 return MEDIATYPE_SCREEN_CAPTURE;
288 } else if (audio && video) {
234 return MEDIATYPE_AUDIO_AND_VIDEO; 289 return MEDIATYPE_AUDIO_AND_VIDEO;
235 } else if (audio) { 290 } else if (audio) {
236 return MEDIATYPE_AUDIO_ONLY; 291 return MEDIATYPE_AUDIO_ONLY;
237 } else if (video) { 292 } else if (video) {
238 return MEDIATYPE_VIDEO_ONLY; 293 return MEDIATYPE_VIDEO_ONLY;
239 } else { 294 } else {
240 return MEDIATYPE_NO_MEDIA; 295 return MEDIATYPE_NO_MEDIA;
241 } 296 }
242 } 297 }
243 298
244 private static boolean shouldStartService(Context context, int mediaType, in t tabId) { 299 private static boolean shouldStartService(Context context, int mediaType, in t tabId) {
245 if (mediaType != MEDIATYPE_NO_MEDIA) return true; 300 if (mediaType != MEDIATYPE_NO_MEDIA) return true;
246 SharedPreferences sharedPreferences = 301 SharedPreferences sharedPreferences =
247 ContextUtils.getAppSharedPreferences(); 302 ContextUtils.getAppSharedPreferences();
248 Set<String> notificationIds = 303 Set<String> notificationIds =
249 sharedPreferences.getStringSet(WEBRTC_NOTIFICATION_IDS, null); 304 sharedPreferences.getStringSet(WEBRTC_NOTIFICATION_IDS, null);
250 if (notificationIds != null 305 if (notificationIds != null
251 && !notificationIds.isEmpty() 306 && !notificationIds.isEmpty()
252 && notificationIds.contains(String.valueOf(tabId))) { 307 && notificationIds.contains(String.valueOf(tabId))) {
253 return true; 308 return true;
254 } 309 }
255 return false; 310 return false;
256 } 311 }
257 312
258 /** 313 /**
259 * Send an intent to MediaCaptureNotificationService to either create, updat e or destroy the 314 * Send an intent to MediaCaptureNotificationService to either create, updat e or destroy the
260 * notification identified by tabId. 315 * notification identified by tabId.
261 * @param tabId Unique notification id. 316 * @param tabId Unique notification id.
262 * @param audio If audio is being captured. 317 * @param mediaType The media type that is being captured.
263 * @param video If video is being captured.
264 * @param fullUrl Url of the current webrtc call. 318 * @param fullUrl Url of the current webrtc call.
265 */ 319 */
266 public static void updateMediaNotificationForTab( 320 public static void updateMediaNotificationForTab(
267 Context context, int tabId, boolean audio, boolean video, String ful lUrl) { 321 Context context, int tabId, int mediaType, String fullUrl) {
268 int mediaType = getMediaType(audio, video);
269 if (!shouldStartService(context, mediaType, tabId)) return; 322 if (!shouldStartService(context, mediaType, tabId)) return;
270 Intent intent = new Intent(context, MediaCaptureNotificationService.clas s); 323 Intent intent = new Intent(context, MediaCaptureNotificationService.clas s);
324 intent.setAction(ACTION_MEDIA_CAPTURE_UPDATE);
271 intent.putExtra(NOTIFICATION_ID_EXTRA, tabId); 325 intent.putExtra(NOTIFICATION_ID_EXTRA, tabId);
272 String baseUrl = fullUrl; 326 String baseUrl = fullUrl;
273 try { 327 try {
274 URL url = new URL(fullUrl); 328 URL url = new URL(fullUrl);
275 baseUrl = url.getProtocol() + "://" + url.getHost(); 329 baseUrl = url.getProtocol() + "://" + url.getHost();
276 } catch (MalformedURLException e) { 330 } catch (MalformedURLException e) {
277 Log.w(TAG, "Error parsing the webrtc url, %s ", fullUrl); 331 Log.w(TAG, "Error parsing the webrtc url, %s ", fullUrl);
278 } 332 }
279 intent.putExtra(NOTIFICATION_MEDIA_URL_EXTRA, baseUrl); 333 intent.putExtra(NOTIFICATION_MEDIA_URL_EXTRA, baseUrl);
280 intent.putExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, mediaType); 334 intent.putExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, mediaType);
281 context.startService(intent); 335 context.startService(intent);
282 } 336 }
283 337
284 /** 338 /**
285 * Clear any previous media notifications. 339 * Clear any previous media notifications.
286 */ 340 */
287 public static void clearMediaNotifications(Context context) { 341 public static void clearMediaNotifications(Context context) {
288 SharedPreferences sharedPreferences = 342 SharedPreferences sharedPreferences =
289 ContextUtils.getAppSharedPreferences(); 343 ContextUtils.getAppSharedPreferences();
290 Set<String> notificationIds = 344 Set<String> notificationIds =
291 sharedPreferences.getStringSet(WEBRTC_NOTIFICATION_IDS, null); 345 sharedPreferences.getStringSet(WEBRTC_NOTIFICATION_IDS, null);
292 if (notificationIds == null || notificationIds.isEmpty()) return; 346 if (notificationIds == null || notificationIds.isEmpty()) return;
293 347
294 context.startService(new Intent(context, MediaCaptureNotificationService .class)); 348 context.startService(new Intent(context, MediaCaptureNotificationService .class));
295 } 349 }
350
351 /**
352 * Build PendingIntent for the actions of screen capture notification.
353 */
354 private PendingIntent buildStopCapturePendingIntent(int notificationId) {
355 Intent intent = new Intent(this, MediaCaptureNotificationService.class);
356 intent.setAction(ACTION_SCREEN_CAPTURE_STOP);
357 intent.putExtra(NOTIFICATION_ID_EXTRA, notificationId);
358 return PendingIntent.getService(
359 mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURR ENT);
360 }
296 } 361 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698