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 |