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

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

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 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 package org.chromium.chrome.browser.media;
6
7 import android.app.Notification;
8 import android.app.NotificationManager;
9 import android.app.PendingIntent;
10 import android.app.Service;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.content.SharedPreferences;
14 import android.os.IBinder;
15 import android.preference.PreferenceManager;
16 import android.provider.Browser;
17 import android.support.v4.app.NotificationCompat;
18 import android.util.Log;
19 import android.util.SparseIntArray;
20
21 import com.google.android.apps.chrome.R;
22
23 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
24 import org.chromium.chrome.browser.Tab;
25
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.Set;
31
32 /**
33 * Service that creates/destroys media related notifications.
34 * There are two kinds of notifications:
35 * 1. The WebRTC notification when media capture starts/stops.
36 * 2. The audio playback notification when a tab is playing audio.
37 * These notifications are made mutually exclusive: there can be
38 * only one media notification for a tab.
39 */
40 public class MediaNotificationService extends Service {
41
42 private static final String NOTIFICATION_NAMESPACE = "MediaNotificationServi ce";
43
44 private static final String NOTIFICATION_ID_EXTRA = "NotificationId";
45 private static final String NOTIFICATION_MEDIA_TYPE_EXTRA = "NotificationMed iaType";
46 private static final String NOTIFICATION_MEDIA_URL_EXTRA = "NotificationMedi aUrl";
47
48 private static final String MEDIA_NOTIFICATION_IDS = "WebRTCNotificationIds" ;
49 private static final String LOG_TAG = "MediaNotificationService";
50
51 private static final int MEDIATYPE_NO_MEDIA = 0;
52 private static final int MEDIATYPE_AUDIO_AND_VIDEO_CAPTURE = 1;
53 private static final int MEDIATYPE_VIDEO_CAPTURE_ONLY = 2;
54 private static final int MEDIATYPE_AUDIO_CAPTURE_ONLY = 3;
55 private static final int MEDIATYPE_AUDIO_PLAYBACK = 4;
56
57 private NotificationManager mNotificationManager;
58 private Context mContext;
59 private SharedPreferences mSharedPreferences;
60 private final SparseIntArray mNotifications = new SparseIntArray();
61
62 @Override
63 public void onCreate() {
64 mContext = getApplicationContext();
65 mNotificationManager = (NotificationManager) mContext.getSystemService(
66 Context.NOTIFICATION_SERVICE);
67 mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mCont ext);
68 super.onCreate();
69 }
70
71 /**
72 * @param notificationId Unique id of the notification.
73 * @param mediaType Media type of the notification.
74 * @return Whether the notification has already been created for provided no tification id and
75 * mediaType.
76 */
77 private boolean doesNotificationNeedUpdate(int notificationId, int mediaType ) {
78 return mNotifications.get(notificationId) != mediaType;
79 }
80
81 /**
82 * @param notificationId Unique id of the notification.
83 * @return Whether the notification has already been created for the provide d notification id.
84 */
85 private boolean doesNotificationExist(int notificationId) {
86 return mNotifications.indexOfKey(notificationId) >= 0;
87 }
88
89 @Override
90 public int onStartCommand(Intent intent, int flags, int startId) {
91 if (intent == null || intent.getExtras() == null) {
92 cancelPreviousWebRtcNotifications();
93 stopSelf();
94 } else {
95 updateNotification(
96 intent.getIntExtra(NOTIFICATION_ID_EXTRA, Tab.INVALID_TAB_ID ),
97 intent.getIntExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, MEDIATYPE_ NO_MEDIA),
98 intent.getStringExtra(NOTIFICATION_MEDIA_URL_EXTRA));
99 }
100 return super.onStartCommand(intent, flags, startId);
101 }
102
103 /**
104 * Cancel all previously existing notifications. Essential while doing a cle an start (may be
105 * after a browser crash which caused old notifications to exist).
106 */
107 private void cancelPreviousWebRtcNotifications() {
108 Set<String> notificationIds =
109 mSharedPreferences.getStringSet(MEDIA_NOTIFICATION_IDS, null);
110 if (notificationIds == null) return;
111 Iterator<String> iterator = notificationIds.iterator();
112 while (iterator.hasNext()) {
113 mNotificationManager.cancel(NOTIFICATION_NAMESPACE, Integer.parseInt (iterator.next()));
114 }
115 SharedPreferences.Editor sharedPreferenceEditor = mSharedPreferences.edi t();
116 sharedPreferenceEditor.remove(MediaNotificationService.MEDIA_NOTIFICATIO N_IDS);
117 sharedPreferenceEditor.apply();
118 }
119
120 /**
121 * Updates the extisting notification or creates one if none exist for the p rovided
122 * notificationId and mediaType.
123 * @param notificationId Unique id of the notification.
124 * @param mediaType Media type of the notification.
125 * @param url Url of the current webrtc call.
126 */
127 private void updateNotification(int notificationId, int mediaType, String ur l) {
128 if (doesNotificationExist(notificationId)
129 && !doesNotificationNeedUpdate(notificationId, mediaType)) {
130 return;
131 }
132 destroyNotification(notificationId);
133 if (mediaType != MEDIATYPE_NO_MEDIA) {
134 createNotification(notificationId, mediaType, url);
135 }
136 if (mNotifications.size() == 0) stopSelf();
137 }
138
139 /**
140 * Destroys the notification for the id notificationId.
141 * @param notificationId Unique id of the notification.
142 */
143 private void destroyNotification(int notificationId) {
144 if (doesNotificationExist(notificationId)) {
145 mNotificationManager.cancel(NOTIFICATION_NAMESPACE, notificationId);
146 mNotifications.delete(notificationId);
147 updateSharedPreferencesEntry(notificationId, true);
148 }
149 }
150
151 /**
152 * Creates a notification for the provided notificationId and mediaType.
153 * @param notificationId Unique id of the notification.
154 * @param mediaType Media type of the notification.
155 * @param url Url of the current webrtc call.
156 */
157 private void createNotification(int notificationId, int mediaType, String ur l) {
158 int notificationContentTextId = 0;
159 int notificationIconId = 0;
160 if (mediaType == MEDIATYPE_AUDIO_AND_VIDEO_CAPTURE) {
161 notificationContentTextId = R.string.video_audio_call_notification_t ext_2;
162 notificationIconId = R.drawable.webrtc_video;
163 } else if (mediaType == MEDIATYPE_VIDEO_CAPTURE_ONLY) {
164 notificationContentTextId = R.string.video_call_notification_text_2;
165 notificationIconId = R.drawable.webrtc_video;
166 } else if (mediaType == MEDIATYPE_AUDIO_CAPTURE_ONLY) {
167 notificationContentTextId = R.string.audio_call_notification_text_2;
168 notificationIconId = R.drawable.webrtc_audio;
169 } else if (mediaType == MEDIATYPE_AUDIO_PLAYBACK) {
170 notificationContentTextId = R.string.audio_playback_notification_tex t;
171 notificationIconId = R.drawable.audio_playing;
172 }
173
174 Intent tabIntent = createMediaTabOpenIntent(notificationId);
175 PendingIntent contentIntent = PendingIntent.getActivity(
176 mContext, notificationId, tabIntent, 0);
177 String contentText = mContext.getResources().getString(notificationConte ntTextId) + ". "
178 + mContext.getResources().getString(
179 R.string.media_notification_link_text, url);
180
181 NotificationCompat.Builder builder = new NotificationCompat.Builder(mCon text)
182 .setAutoCancel(false)
183 .setOngoing(true)
184 .setContentIntent(contentIntent)
185 .setContentTitle(mContext.getString(R.string.app_name))
186 .setContentText(contentText)
187 .setSmallIcon(notificationIconId)
188 .setLocalOnly(true);
189
190 Notification notification = new NotificationCompat.BigTextStyle(builder)
191 .bigText(contentText).build();
192 mNotificationManager.notify(NOTIFICATION_NAMESPACE, notificationId, noti fication);
193 mNotifications.put(notificationId, mediaType);
194 updateSharedPreferencesEntry(notificationId, false);
195 }
196
197 /**
198 * Returns the Intent that opens the tab with the WebRTC call on click of th e notification.
199 */
200 private Intent createMediaTabOpenIntent(int tabId) {
201 Intent intent = new Intent(Intent.ACTION_MAIN);
202 intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName()) ;
203 intent.putExtra(TabOpenType.BRING_TAB_TO_FRONT.name(), tabId);
204 intent.setPackage(mContext.getPackageName());
205 return intent;
206 }
207
208 /**
209 * Update shared preferences entry with ids of the visible notifications.
210 * @param notificationId Id of the notification.
211 * @param remove Boolean describing if the notification was added or removed .
212 */
213 private void updateSharedPreferencesEntry(int notificationId, boolean remove ) {
214 Set<String> notificationIds =
215 new HashSet<String>(mSharedPreferences.getStringSet(MEDIA_NOTIFI CATION_IDS,
216 new HashSet<String>()));
217 if (remove && !notificationIds.isEmpty()
218 && notificationIds.contains(String.valueOf(notificationId))) {
219 notificationIds.remove(String.valueOf(notificationId));
220 } else if (!remove) {
221 notificationIds.add(String.valueOf(notificationId));
222 }
223 SharedPreferences.Editor sharedPreferenceEditor = mSharedPreferences.ed it();
224 sharedPreferenceEditor.putStringSet(MEDIA_NOTIFICATION_IDS, notification Ids);
225 sharedPreferenceEditor.apply();
226 }
227
228 @Override
229 public void onDestroy() {
230 cancelPreviousWebRtcNotifications();
231 super.onDestroy();
232 }
233
234 @Override
235 public boolean onUnbind(Intent intent) {
236 cancelPreviousWebRtcNotifications();
237 return super.onUnbind(intent);
238 }
239
240 @Override
241 public IBinder onBind(Intent intent) {
242 return null;
243 }
244
245 /**
246 * @param audio If audio is being captured.
247 * @param video If video is being captured.
248 * @return A constant identify what media is being captured.
249 */
250 public static int getMediaType(boolean audioCapture,
251 boolean videoCapture, boolean audioPlayback) {
252 if (audioCapture && videoCapture) {
253 return MEDIATYPE_AUDIO_AND_VIDEO_CAPTURE;
254 } else if (audioCapture) {
255 return MEDIATYPE_AUDIO_CAPTURE_ONLY;
256 } else if (videoCapture) {
257 return MEDIATYPE_VIDEO_CAPTURE_ONLY;
258 } else if (audioPlayback) {
259 return MEDIATYPE_AUDIO_PLAYBACK;
260 } else {
261 return MEDIATYPE_NO_MEDIA;
262 }
263 }
264
265 private static boolean shouldStartService(Context context, int mediaType, in t tabId) {
266 if (mediaType != MEDIATYPE_NO_MEDIA) return true;
267 SharedPreferences sharedPreferences =
268 PreferenceManager.getDefaultSharedPreferences(context);
269 Set<String> notificationIds =
270 sharedPreferences.getStringSet(MEDIA_NOTIFICATION_IDS, null);
271 if (notificationIds != null
272 && !notificationIds.isEmpty()
273 && notificationIds.contains(String.valueOf(tabId))) {
274 return true;
275 }
276 return false;
277 }
278
279 /**
280 * Send an intent to MediaNotificationService to either create, update or de stroy the
281 * notification identified by tabId.
282 * @param tabId Unique notification id.
283 * @param audio If audio is being captured.
284 * @param video If video is being captured.
285 * @param fullUrl Url of the current webrtc call.
286 */
287 public static void updateMediaNotificationForTab(Context context, int tabId,
288 boolean audioCapture, boolean videoCapture, boolean audioPlayback,
289 String fullUrl) {
290 int mediaType = getMediaType(audioCapture, videoCapture, audioPlayback);
291 if (!shouldStartService(context, mediaType, tabId)) return;
292 Intent intent = new Intent(context, MediaNotificationService.class);
293 intent.putExtra(NOTIFICATION_ID_EXTRA, tabId);
294 String baseUrl = fullUrl;
295 try {
296 URL url = new URL(fullUrl);
297 baseUrl = url.getProtocol() + "://" + url.getHost();
298 } catch (MalformedURLException e) {
299 Log.w(LOG_TAG, "Error parsing the webrtc url " + fullUrl);
300 }
301 intent.putExtra(NOTIFICATION_MEDIA_URL_EXTRA, baseUrl);
302 intent.putExtra(NOTIFICATION_MEDIA_TYPE_EXTRA, mediaType);
303 context.startService(intent);
304 }
305
306 /**
307 * Clear any previous media notifications.
308 */
309 public static void clearMediaNotifications(Context context) {
310 SharedPreferences sharedPreferences =
311 PreferenceManager.getDefaultSharedPreferences(context);
312 Set<String> notificationIds =
313 sharedPreferences.getStringSet(MEDIA_NOTIFICATION_IDS, null);
314 if (notificationIds == null || notificationIds.isEmpty()) return;
315
316 context.startService(new Intent(context, MediaNotificationService.class) );
317 }
318 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698