Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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.ntp; | 5 package org.chromium.chrome.browser.ntp; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | |
| 8 import android.app.AlarmManager; | 7 import android.app.AlarmManager; |
| 9 import android.app.NotificationManager; | 8 import android.app.NotificationManager; |
| 10 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
| 11 import android.content.BroadcastReceiver; | 10 import android.content.BroadcastReceiver; |
| 12 import android.content.Context; | 11 import android.content.Context; |
| 13 import android.content.Intent; | 12 import android.content.Intent; |
| 14 import android.content.SharedPreferences; | 13 import android.content.SharedPreferences; |
| 15 import android.graphics.Bitmap; | 14 import android.graphics.Bitmap; |
| 16 import android.net.Uri; | 15 import android.net.Uri; |
| 17 import android.os.Build; | |
| 18 import android.provider.Browser; | 16 import android.provider.Browser; |
| 19 import android.service.notification.StatusBarNotification; | |
| 20 import android.support.v4.app.NotificationCompat; | 17 import android.support.v4.app.NotificationCompat; |
| 21 | 18 |
| 22 import org.chromium.base.ContextUtils; | 19 import org.chromium.base.ContextUtils; |
| 23 import org.chromium.base.annotations.CalledByNative; | 20 import org.chromium.base.annotations.CalledByNative; |
| 24 import org.chromium.base.annotations.JNINamespace; | 21 import org.chromium.base.annotations.JNINamespace; |
| 25 import org.chromium.base.library_loader.LibraryLoader; | 22 import org.chromium.base.library_loader.LibraryLoader; |
| 26 import org.chromium.chrome.R; | 23 import org.chromium.chrome.R; |
| 27 import org.chromium.chrome.browser.IntentHandler; | 24 import org.chromium.chrome.browser.IntentHandler; |
| 28 import org.chromium.chrome.browser.ShortcutHelper; | 25 import org.chromium.chrome.browser.ShortcutHelper; |
| 29 import org.chromium.chrome.browser.document.ChromeLauncherActivity; | 26 import org.chromium.chrome.browser.document.ChromeLauncherActivity; |
| 27 import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsNotificationAc tion; | |
| 28 | |
| 29 import java.util.HashSet; | |
| 30 import java.util.Set; | |
| 30 | 31 |
| 31 /** | 32 /** |
| 32 * Provides functionality needed for content suggestion notifications. | 33 * Provides functionality needed for content suggestion notifications. |
| 33 * | 34 * |
| 34 * Exposes helper functions to native C++ code. | 35 * Exposes helper functions to native C++ code. |
| 35 */ | 36 */ |
| 36 @JNINamespace("ntp_snippets") | 37 @JNINamespace("ntp_snippets") |
| 37 public class ContentSuggestionsNotificationHelper { | 38 public class ContentSuggestionsNotificationHelper { |
| 38 private static final String NOTIFICATION_TAG = "ContentSuggestionsNotificati on"; | 39 private static final String NOTIFICATION_TAG = "ContentSuggestionsNotificati on"; |
| 39 private static final String NOTIFICATION_ID_EXTRA = "notification_id"; | 40 private static final String NOTIFICATION_ID_EXTRA = "notification_id"; |
| 41 private static final String NOTIFICATION_CATEGORY_EXTRA = "category"; | |
| 42 private static final String NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA = "id_with in_category"; | |
| 40 | 43 |
| 41 private static final String PREF_CACHED_ACTION_TAP = | 44 private static final String PREF_CACHED_ACTION_TAP = |
| 42 "ntp.content_suggestions.notification.cached_action_tap"; | 45 "ntp.content_suggestions.notification.cached_action_tap"; |
| 43 private static final String PREF_CACHED_ACTION_DISMISSAL = | 46 private static final String PREF_CACHED_ACTION_DISMISSAL = |
| 44 "ntp.content_suggestions.notification.cached_action_dismissal"; | 47 "ntp.content_suggestions.notification.cached_action_dismissal"; |
| 45 private static final String PREF_CACHED_ACTION_HIDE_DEADLINE = | 48 private static final String PREF_CACHED_ACTION_HIDE_DEADLINE = |
| 46 "ntp.content_suggestions.notification.cached_action_hide_deadline"; | 49 "ntp.content_suggestions.notification.cached_action_hide_deadline"; |
| 50 private static final String PREF_CACHED_ACTION_HIDE_EXPIRY = | |
| 51 "ntp.content_suggestions.notification.cached_action_hide_expiry"; | |
| 52 private static final String PREF_CACHED_ACTION_HIDE_FRONTMOST = | |
| 53 "ntp.content_suggestions.notification.cached_action_hide_frontmost"; | |
| 54 private static final String PREF_CACHED_ACTION_HIDE_DISABLED = | |
| 55 "ntp.content_suggestions.notification.cached_action_hide_disabled"; | |
| 56 private static final String PREF_CACHED_ACTION_HIDE_SHUTDOWN = | |
| 57 "ntp.content_suggestions.notification.cached_action_hide_shutdown"; | |
| 47 private static final String PREF_CACHED_CONSECUTIVE_IGNORED = | 58 private static final String PREF_CACHED_CONSECUTIVE_IGNORED = |
| 48 "ntp.content_suggestions.notification.cached_consecutive_ignored"; | 59 "ntp.content_suggestions.notification.cached_consecutive_ignored"; |
| 49 | 60 |
| 61 // Tracks which URIs there is an active notification for. | |
| 62 private static final String PREF_ACTIVE_NOTIFICATIONS = | |
| 63 "ntp.content_suggestions.notification.active"; | |
| 64 | |
| 50 private ContentSuggestionsNotificationHelper() {} // Prevent instantiation | 65 private ContentSuggestionsNotificationHelper() {} // Prevent instantiation |
| 51 | 66 |
| 52 /** | 67 /** |
| 53 * Opens the content suggestion when notification is tapped. | 68 * Opens the content suggestion when notification is tapped. |
| 54 */ | 69 */ |
| 55 public static final class OpenUrlReceiver extends BroadcastReceiver { | 70 public static final class OpenUrlReceiver extends BroadcastReceiver { |
| 56 public void onReceive(Context context, Intent intent) { | 71 public void onReceive(Context context, Intent intent) { |
| 72 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); | |
| 73 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); | |
| 57 openUrl(intent.getData()); | 74 openUrl(intent.getData()); |
| 58 recordCachedActionMetric(PREF_CACHED_ACTION_TAP); | 75 recordCachedActionMetric(ContentSuggestionsNotificationAction.CONTEN T_SUGGESTIONS_TAP); |
| 76 removeActiveNotification(category, idWithinCategory); | |
| 59 } | 77 } |
| 60 } | 78 } |
| 61 | 79 |
| 62 /** | 80 /** |
| 63 * Records dismissal when notification is swiped away. | 81 * Records dismissal when notification is swiped away. |
| 64 */ | 82 */ |
| 65 public static final class DeleteReceiver extends BroadcastReceiver { | 83 public static final class DeleteReceiver extends BroadcastReceiver { |
| 66 public void onReceive(Context context, Intent intent) { | 84 public void onReceive(Context context, Intent intent) { |
| 67 recordCachedActionMetric(PREF_CACHED_ACTION_DISMISSAL); | 85 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); |
| 86 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); | |
| 87 recordCachedActionMetric( | |
| 88 ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_DIS MISSAL); | |
| 89 removeActiveNotification(category, idWithinCategory); | |
| 68 } | 90 } |
| 69 } | 91 } |
| 70 | 92 |
| 71 /** | 93 /** |
| 72 * Removes the notification after a timeout period. | 94 * Removes the notification after a timeout period. |
| 73 */ | 95 */ |
| 74 public static final class TimeoutReceiver extends BroadcastReceiver { | 96 public static final class TimeoutReceiver extends BroadcastReceiver { |
| 75 public void onReceive(Context context, Intent intent) { | 97 public void onReceive(Context context, Intent intent) { |
| 98 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); | |
| 99 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); | |
| 100 if (findActiveNotification(category, idWithinCategory) == null) { | |
| 101 return; // tapped or swiped | |
| 102 } | |
| 103 | |
| 76 int id = intent.getIntExtra(NOTIFICATION_ID_EXTRA, -1); | 104 int id = intent.getIntExtra(NOTIFICATION_ID_EXTRA, -1); |
| 77 if (id < 0) return; | 105 hideNotification(category, idWithinCategory, |
| 78 hideNotification(id); | 106 ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HID E_DEADLINE); |
| 79 recordCachedActionMetric(PREF_CACHED_ACTION_HIDE_DEADLINE); | |
| 80 } | 107 } |
| 81 } | 108 } |
| 82 | 109 |
| 83 private static void openUrl(Uri uri) { | 110 private static void openUrl(Uri uri) { |
| 84 Context context = ContextUtils.getApplicationContext(); | 111 Context context = ContextUtils.getApplicationContext(); |
| 85 Intent intent = new Intent() | 112 Intent intent = new Intent() |
| 86 .setAction(Intent.ACTION_VIEW) | 113 .setAction(Intent.ACTION_VIEW) |
| 87 .setData(uri) | 114 .setData(uri) |
| 88 .setClass(context, ChromeLauncherActivity.class) | 115 .setClass(context, ChromeLauncherActivity.class) |
| 89 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | 116 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
| 90 .putExtra(Browser.EXTRA_APPLICATION_ID, context. getPackageName()) | 117 .putExtra(Browser.EXTRA_APPLICATION_ID, context. getPackageName()) |
| 91 .putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ ELSE_NEW_TAB, true); | 118 .putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ ELSE_NEW_TAB, true); |
| 92 IntentHandler.addTrustedIntentExtras(intent); | 119 IntentHandler.addTrustedIntentExtras(intent); |
| 93 context.startActivity(intent); | 120 context.startActivity(intent); |
| 94 } | 121 } |
| 95 | 122 |
| 96 @TargetApi(Build.VERSION_CODES.M) | |
| 97 @CalledByNative | 123 @CalledByNative |
| 98 private static void showNotification( | 124 private static boolean showNotification(int category, String idWithinCategor y, String url, |
| 99 String url, String title, String text, Bitmap image, long timeoutAtM illis) { | 125 String title, String text, Bitmap image, long timeoutAtMillis) { |
| 126 if (findActiveNotification(category, idWithinCategory) != null) return f alse; | |
| 127 | |
| 100 // Post notification. | 128 // Post notification. |
| 101 Context context = ContextUtils.getApplicationContext(); | 129 Context context = ContextUtils.getApplicationContext(); |
| 102 NotificationManager manager = | 130 NotificationManager manager = |
| 103 (NotificationManager) context.getSystemService(Context.NOTIFICAT ION_SERVICE); | 131 (NotificationManager) context.getSystemService(Context.NOTIFICAT ION_SERVICE); |
| 104 | 132 |
| 105 // Find an available notification ID. | 133 int nextId = nextNotificationId(); |
| 106 int nextId = 0; | 134 Uri uri = Uri.parse(url); |
| 107 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | 135 Intent contentIntent = |
| 108 for (StatusBarNotification activeNotification : manager.getActiveNot ifications()) { | 136 new Intent(context, OpenUrlReceiver.class) |
| 109 if (activeNotification.getTag() != NOTIFICATION_TAG) continue; | 137 .setData(uri) |
| 110 if (activeNotification.getId() >= nextId) { | 138 .putExtra(NOTIFICATION_CATEGORY_EXTRA, category) |
| 111 nextId = activeNotification.getId() + 1; | 139 .putExtra(NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA, idWithi nCategory); |
| 112 } | 140 Intent deleteIntent = |
| 113 } | 141 new Intent(context, DeleteReceiver.class) |
| 114 } | 142 .setData(uri) |
| 115 | 143 .putExtra(NOTIFICATION_CATEGORY_EXTRA, category) |
| 116 Intent contentIntent = new Intent(context, OpenUrlReceiver.class).setDat a(Uri.parse(url)); | 144 .putExtra(NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA, idWithi nCategory); |
| 117 Intent deleteIntent = new Intent(context, DeleteReceiver.class).setData( Uri.parse(url)); | |
| 118 NotificationCompat.Builder builder = | 145 NotificationCompat.Builder builder = |
| 119 new NotificationCompat.Builder(context) | 146 new NotificationCompat.Builder(context) |
| 120 .setAutoCancel(true) | 147 .setAutoCancel(true) |
| 121 .setContentIntent(PendingIntent.getBroadcast(context, 0, contentIntent, 0)) | 148 .setContentIntent(PendingIntent.getBroadcast(context, 0, contentIntent, 0)) |
| 122 .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0)) | 149 .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0)) |
| 123 .setContentTitle(title) | 150 .setContentTitle(title) |
| 124 .setContentText(text) | 151 .setContentText(text) |
| 125 .setGroup(NOTIFICATION_TAG) | 152 .setGroup(NOTIFICATION_TAG) |
| 126 .setLargeIcon(image) | 153 .setLargeIcon(image) |
| 127 .setSmallIcon(R.drawable.ic_chrome); | 154 .setSmallIcon(R.drawable.ic_chrome); |
| 128 manager.notify(NOTIFICATION_TAG, nextId, builder.build()); | 155 manager.notify(NOTIFICATION_TAG, nextId, builder.build()); |
| 156 addActiveNotification(new ActiveNotification(nextId, category, idWithinC ategory, uri)); | |
| 129 | 157 |
| 130 // Set timeout. | 158 // Set timeout. |
| 131 if (timeoutAtMillis != Long.MAX_VALUE) { | 159 if (timeoutAtMillis != Long.MAX_VALUE) { |
| 132 AlarmManager alarmManager = | 160 AlarmManager alarmManager = |
| 133 (AlarmManager) context.getSystemService(Context.ALARM_SERVIC E); | 161 (AlarmManager) context.getSystemService(Context.ALARM_SERVIC E); |
| 134 Intent timeoutIntent = new Intent(context, TimeoutReceiver.class) | 162 Intent timeoutIntent = |
| 135 .setData(Uri.parse(url)) | 163 new Intent(context, TimeoutReceiver.class) |
| 136 .putExtra(NOTIFICATION_ID_EXTRA, next Id); | 164 .setData(Uri.parse(url)) |
| 165 .putExtra(NOTIFICATION_ID_EXTRA, nextId) | |
| 166 .putExtra(NOTIFICATION_CATEGORY_EXTRA, category) | |
| 167 .putExtra(NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA, idW ithinCategory); | |
| 137 alarmManager.set(AlarmManager.RTC, timeoutAtMillis, | 168 alarmManager.set(AlarmManager.RTC, timeoutAtMillis, |
| 138 PendingIntent.getBroadcast( | 169 PendingIntent.getBroadcast( |
| 139 context, 0, timeoutIntent, PendingIntent.FLAG_UPDATE _CURRENT)); | 170 context, 0, timeoutIntent, PendingIntent.FLAG_UPDATE _CURRENT)); |
| 140 } | 171 } |
| 172 return true; | |
| 141 } | 173 } |
| 142 | 174 |
| 143 private static void hideNotification(int id) { | 175 @CalledByNative |
| 176 private static void hideNotification(int category, String idWithinCategory, int why) { | |
| 144 Context context = ContextUtils.getApplicationContext(); | 177 Context context = ContextUtils.getApplicationContext(); |
| 145 NotificationManager manager = | 178 NotificationManager manager = |
| 146 (NotificationManager) context.getSystemService(Context.NOTIFICAT ION_SERVICE); | 179 (NotificationManager) context.getSystemService(Context.NOTIFICAT ION_SERVICE); |
| 147 manager.cancel(NOTIFICATION_TAG, id); | 180 if (removeActiveNotification(category, idWithinCategory)) { |
| 181 recordCachedActionMetric(why); | |
| 182 } | |
| 148 } | 183 } |
| 149 | 184 |
| 150 @TargetApi(Build.VERSION_CODES.M) | |
| 151 @CalledByNative | 185 @CalledByNative |
| 152 private static void hideAllNotifications() { | 186 private static void hideAllNotifications(int why) { |
| 153 Context context = ContextUtils.getApplicationContext(); | 187 Context context = ContextUtils.getApplicationContext(); |
| 154 NotificationManager manager = | 188 NotificationManager manager = |
| 155 (NotificationManager) context.getSystemService(Context.NOTIFICAT ION_SERVICE); | 189 (NotificationManager) context.getSystemService(Context.NOTIFICAT ION_SERVICE); |
| 156 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | 190 for (ActiveNotification activeNotification : getActiveNotifications()) { |
| 157 for (StatusBarNotification activeNotification : manager.getActiveNot ifications()) { | 191 manager.cancel(NOTIFICATION_TAG, activeNotification.mId); |
| 158 if (activeNotification.getTag() == NOTIFICATION_TAG) { | 192 recordCachedActionMetric(why); |
| 159 manager.cancel(NOTIFICATION_TAG, activeNotification.getId()) ; | |
| 160 } | |
| 161 } | |
| 162 } else { | |
| 163 manager.cancel(NOTIFICATION_TAG, 0); | |
| 164 } | 193 } |
| 165 } | 194 } |
| 166 | 195 |
| 196 private static class ActiveNotification { | |
| 197 int mId; | |
|
Bernhard Bauer
2017/01/17 15:56:55
Can you make these final?
sfiera
2017/01/17 17:32:08
Done.
| |
| 198 int mCategory; | |
| 199 String mIdWithinCategory; | |
| 200 Uri mUri; | |
| 201 | |
| 202 ActiveNotification(int id, int category, String idWithinCategory, Uri ur i) { | |
| 203 mId = id; | |
| 204 mCategory = category; | |
| 205 mIdWithinCategory = idWithinCategory; | |
| 206 mUri = uri; | |
| 207 } | |
| 208 | |
| 209 /** Parses the fields out of a chrome://content-suggestions-notification URI */ | |
| 210 static ActiveNotification fromUri(Uri notificationUri) { | |
| 211 if (!notificationUri.getScheme().equals("chrome")) return null; | |
|
Bernhard Bauer
2017/01/17 15:56:55
We shouldn't really get a malformed URL here, righ
sfiera
2017/01/17 17:32:08
Sure, done.
Bernhard Bauer
2017/01/17 18:01:06
Integer.parseInt() might choke though, right? Anyw
| |
| 212 if (!notificationUri.getAuthority().equals("content-suggestions-noti fication")) { | |
| 213 return null; | |
| 214 } | |
| 215 if (notificationUri.getQueryParameter("id") == null) return null; | |
| 216 if (notificationUri.getQueryParameter("category") == null) return nu ll; | |
| 217 if (notificationUri.getQueryParameter("idWithinCategory") == null) r eturn null; | |
| 218 if (notificationUri.getQueryParameter("uri") == null) return null; | |
| 219 | |
| 220 return new ActiveNotification(Integer.parseInt(notificationUri.getQu eryParameter("id")), | |
| 221 Integer.parseInt(notificationUri.getQueryParameter("category ")), | |
| 222 notificationUri.getQueryParameter("idWithinCategory"), | |
| 223 Uri.parse(notificationUri.getQueryParameter("uri"))); | |
| 224 } | |
| 225 | |
| 226 /** Serializes the fields to a chrome://content-suggestions-notification URI */ | |
| 227 Uri toUri() { | |
| 228 return new Uri.Builder() | |
| 229 .scheme("chrome") | |
| 230 .authority("content-suggestions-notification") | |
| 231 .appendQueryParameter("id", Integer.toString(mId)) | |
| 232 .appendQueryParameter("category", Integer.toString(mCategory )) | |
| 233 .appendQueryParameter("idWithinCategory", mIdWithinCategory) | |
| 234 .appendQueryParameter("uri", mUri.toString()) | |
| 235 .build(); | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 private static void addActiveNotification(ActiveNotification notification) { | |
| 240 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | |
| 241 Set<String> activeNotifications = prefs.getStringSet(PREF_ACTIVE_NOTIFIC ATIONS, null); | |
| 242 if (activeNotifications == null) activeNotifications = new HashSet<Strin g>(); | |
| 243 activeNotifications.add(notification.toUri().toString()); | |
|
Bernhard Bauer
2017/01/17 15:56:55
You are not allowed to modify the set returned by
sfiera
2017/01/17 17:32:08
Done.
| |
| 244 prefs.edit().putStringSet(PREF_ACTIVE_NOTIFICATIONS, activeNotifications ).apply(); | |
| 245 } | |
| 246 | |
| 247 private static boolean removeActiveNotification(int category, String idWithi nCategory) { | |
| 248 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | |
| 249 ActiveNotification notification = findActiveNotification(category, idWit hinCategory); | |
| 250 if (notification == null) return false; | |
| 251 | |
| 252 Set<String> activeNotifications = prefs.getStringSet(PREF_ACTIVE_NOTIFIC ATIONS, null); | |
| 253 if (activeNotifications == null) return false; | |
| 254 boolean result = activeNotifications.remove(notification.toUri().toStrin g()); | |
| 255 prefs.edit().putStringSet(PREF_ACTIVE_NOTIFICATIONS, activeNotifications ).apply(); | |
| 256 return result; | |
| 257 } | |
| 258 | |
| 259 private static Set<ActiveNotification> getActiveNotifications() { | |
| 260 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | |
| 261 Set<String> activeNotifications = prefs.getStringSet(PREF_ACTIVE_NOTIFIC ATIONS, null); | |
| 262 if (activeNotifications == null) return new HashSet<ActiveNotification>( ); | |
| 263 | |
| 264 Set<ActiveNotification> result = new HashSet<ActiveNotification>(); | |
| 265 for (String serialized : activeNotifications) { | |
| 266 Uri notificationUri = Uri.parse(serialized); | |
| 267 ActiveNotification activeNotification = ActiveNotification.fromUri(n otificationUri); | |
| 268 if (activeNotification != null) result.add(activeNotification); | |
| 269 } | |
| 270 return result; | |
| 271 } | |
| 272 | |
| 273 private static ActiveNotification findActiveNotification( | |
| 274 int category, String idWithinCategory) { | |
| 275 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | |
| 276 Set<String> activeNotifications = prefs.getStringSet(PREF_ACTIVE_NOTIFIC ATIONS, null); | |
| 277 if (activeNotifications == null) return null; | |
| 278 | |
| 279 for (String serialized : activeNotifications) { | |
| 280 Uri notificationUri = Uri.parse(serialized); | |
| 281 ActiveNotification activeNotification = ActiveNotification.fromUri(n otificationUri); | |
| 282 if ((activeNotification != null) && (activeNotification.mCategory == category) | |
| 283 && (activeNotification.mIdWithinCategory.equals(idWithinCate gory))) { | |
| 284 return activeNotification; | |
| 285 } | |
| 286 } | |
| 287 return null; | |
| 288 } | |
| 289 | |
| 290 private static int nextNotificationId() { | |
| 291 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | |
| 292 Set<String> activeNotifications = prefs.getStringSet(PREF_ACTIVE_NOTIFIC ATIONS, null); | |
| 293 if (activeNotifications == null) return 0; | |
| 294 | |
| 295 int nextId = 0; | |
| 296 for (String serialized : activeNotifications) { | |
| 297 Uri notificationUri = Uri.parse(serialized); | |
| 298 ActiveNotification activeNotification = ActiveNotification.fromUri(n otificationUri); | |
| 299 if ((activeNotification != null) && (activeNotification.mId >= nextI d)) { | |
| 300 nextId = activeNotification.mId + 1; | |
| 301 } | |
| 302 } | |
| 303 return nextId; | |
| 304 } | |
| 305 | |
| 306 public static String cachedMetricNameForAction( | |
|
Bernhard Bauer
2017/01/17 15:56:55
Javadoc for public methods please.
sfiera
2017/01/17 17:32:08
Oops, shouldn't have been public.
| |
| 307 @ContentSuggestionsNotificationAction.ContentSuggestionsNotification ActionEnum | |
| 308 int action) { | |
| 309 switch (action) { | |
| 310 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_TAP: | |
| 311 return PREF_CACHED_ACTION_TAP; | |
| 312 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_DISMIS SAL: | |
| 313 return PREF_CACHED_ACTION_DISMISSAL; | |
| 314 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_D EADLINE: | |
| 315 return PREF_CACHED_ACTION_HIDE_DEADLINE; | |
| 316 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_E XPIRY: | |
| 317 return PREF_CACHED_ACTION_HIDE_EXPIRY; | |
| 318 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_F RONTMOST: | |
| 319 return PREF_CACHED_ACTION_HIDE_FRONTMOST; | |
| 320 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_D ISABLED: | |
| 321 return PREF_CACHED_ACTION_HIDE_DISABLED; | |
| 322 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_S HUTDOWN: | |
| 323 return PREF_CACHED_ACTION_HIDE_SHUTDOWN; | |
| 324 } | |
| 325 return ""; | |
| 326 } | |
| 327 | |
| 167 /** | 328 /** |
| 168 * Records that an action was performed on a notification. | 329 * Records that an action was performed on a notification. |
| 169 * | 330 * |
| 170 * Also tracks the number of consecutively-ignored notifications, resetting it on a tap or | 331 * Also tracks the number of consecutively-ignored notifications, resetting it on a tap or |
| 171 * otherwise incrementing it. | 332 * otherwise incrementing it. |
| 172 * | 333 * |
| 173 * This method may be called when the native library is not loaded. If it is loaded, the metrics | 334 * This method may be called when the native library is not loaded. If it is loaded, the metrics |
| 174 * will immediately be sent to C++. If not, it will cache them for a later c all to | 335 * will immediately be sent to C++. If not, it will cache them for a later c all to |
| 175 * flushCachedMetrics(). | 336 * flushCachedMetrics(). |
| 176 * | 337 * |
| 177 * @param prefName The name of the action metric pref to update (<tt>PREF_CA CHED_ACTION_*</tt>) | 338 * @param action The action to update the pref for. |
| 178 */ | 339 */ |
| 179 private static void recordCachedActionMetric(String prefName) { | 340 private static void recordCachedActionMetric( |
| 180 assert prefName.startsWith("ntp.content_suggestions.notification.cached_ action_"); | 341 @ContentSuggestionsNotificationAction.ContentSuggestionsNotification ActionEnum |
| 342 int action) { | |
| 343 String prefName = cachedMetricNameForAction(action); | |
| 344 assert !prefName.isEmpty(); | |
| 181 | 345 |
| 182 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | 346 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); |
| 183 int currentValue = prefs.getInt(prefName, 0); | 347 int currentValue = prefs.getInt(prefName, 0); |
| 184 int consecutiveIgnored = 0; | 348 int consecutiveIgnored = 0; |
| 185 if (!prefName.equals(PREF_CACHED_ACTION_TAP)) { | 349 if (action != ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_T AP) { |
| 186 consecutiveIgnored = 1 + prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORE D, 0); | 350 consecutiveIgnored = 1 + prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORE D, 0); |
| 187 } | 351 } |
| 188 prefs.edit() | 352 prefs.edit() |
| 189 .putInt(prefName, currentValue + 1) | 353 .putInt(prefName, currentValue + 1) |
| 190 .putInt(PREF_CACHED_CONSECUTIVE_IGNORED, consecutiveIgnored) | 354 .putInt(PREF_CACHED_CONSECUTIVE_IGNORED, consecutiveIgnored) |
| 191 .apply(); | 355 .apply(); |
| 192 | 356 |
| 193 if (LibraryLoader.isInitialized()) { | 357 if (LibraryLoader.isInitialized()) { |
| 194 flushCachedMetrics(); | 358 flushCachedMetrics(); |
| 195 } | 359 } |
| 196 } | 360 } |
| 197 | 361 |
| 198 /** | 362 /** |
| 199 * Invokes nativeReceiveFlushedMetrics() with cached metrics and resets them . | 363 * Invokes nativeReceiveFlushedMetrics() with cached metrics and resets them . |
| 200 * | 364 * |
| 201 * It may be called from either native or Java code, as long as the native l ibray is loaded. | 365 * It may be called from either native or Java code, as long as the native l ibray is loaded. |
| 202 */ | 366 */ |
| 203 @CalledByNative | 367 @CalledByNative |
| 204 private static void flushCachedMetrics() { | 368 private static void flushCachedMetrics() { |
| 205 assert LibraryLoader.isInitialized(); | 369 assert LibraryLoader.isInitialized(); |
| 206 | 370 |
| 207 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | 371 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); |
| 208 int tapCount = prefs.getInt(PREF_CACHED_ACTION_TAP, 0); | 372 int tapCount = prefs.getInt(PREF_CACHED_ACTION_TAP, 0); |
| 209 int dismissalCount = prefs.getInt(PREF_CACHED_ACTION_DISMISSAL, 0); | 373 int dismissalCount = prefs.getInt(PREF_CACHED_ACTION_DISMISSAL, 0); |
| 210 int hideDeadlineCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_DEADLINE, 0 ); | 374 int hideDeadlineCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_DEADLINE, 0 ); |
| 375 int hideExpiryCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_EXPIRY, 0); | |
| 376 int hideFrontmostCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_FRONTMOST, 0); | |
| 377 int hideDisabledCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_DISABLED, 0 ); | |
| 378 int hideShutdownCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_SHUTDOWN, 0 ); | |
| 211 int consecutiveIgnored = prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0 ); | 379 int consecutiveIgnored = prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0 ); |
| 212 | 380 |
| 213 if (tapCount > 0 || dismissalCount > 0 || hideDeadlineCount > 0) { | 381 if (tapCount > 0 || dismissalCount > 0 || hideDeadlineCount > 0 || hideE xpiryCount > 0 |
| 382 || hideFrontmostCount > 0 || hideDisabledCount > 0 || hideShutdo wnCount > 0) { | |
| 214 nativeReceiveFlushedMetrics(tapCount, dismissalCount, hideDeadlineCo unt, | 383 nativeReceiveFlushedMetrics(tapCount, dismissalCount, hideDeadlineCo unt, |
| 215 consecutiveIgnored); | 384 hideExpiryCount, hideFrontmostCount, hideDisabledCount, hide ShutdownCount, |
| 385 consecutiveIgnored); | |
| 216 prefs.edit() | 386 prefs.edit() |
| 217 .remove(PREF_CACHED_ACTION_TAP) | 387 .remove(PREF_CACHED_ACTION_TAP) |
| 218 .remove(PREF_CACHED_ACTION_DISMISSAL) | 388 .remove(PREF_CACHED_ACTION_DISMISSAL) |
| 219 .remove(PREF_CACHED_ACTION_HIDE_DEADLINE) | 389 .remove(PREF_CACHED_ACTION_HIDE_DEADLINE) |
| 390 .remove(PREF_CACHED_ACTION_HIDE_EXPIRY) | |
| 391 .remove(PREF_CACHED_ACTION_HIDE_FRONTMOST) | |
| 392 .remove(PREF_CACHED_ACTION_HIDE_DISABLED) | |
| 393 .remove(PREF_CACHED_ACTION_HIDE_SHUTDOWN) | |
| 220 .remove(PREF_CACHED_CONSECUTIVE_IGNORED) | 394 .remove(PREF_CACHED_CONSECUTIVE_IGNORED) |
| 221 .apply(); | 395 .apply(); |
| 222 } | 396 } |
| 223 } | 397 } |
| 224 | 398 |
| 225 private static native void nativeReceiveFlushedMetrics( | 399 private static native void nativeReceiveFlushedMetrics(int tapCount, int dis missalCount, |
| 226 int tapCount, int dismissalCount, int hideDeadlineCount, int consecu tiveIgnored); | 400 int hideDeadlineCount, int hideExpiryCount, int hideFrontmostCount, |
| 401 int hideDisabledCount, int hideShutdownCount, int consecutiveIgnored ); | |
| 227 } | 402 } |
| OLD | NEW |