blob: fd893fa081a52571cfcd7da7f1ce8a279ec03958 [file] [log] [blame]
Chris Wren333a61c2014-05-28 16:40:57 -04001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.notification;
17
Julia Reynoldsf0f629f2016-02-25 09:34:04 -050018import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MIN;
Chris Wren47633422016-01-22 09:56:59 -050019import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
Chris Wrenbdf33762015-12-04 15:50:51 -050020import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
21import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
22import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
23import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
24
Chris Wren333a61c2014-05-28 16:40:57 -040025import android.app.Notification;
26import android.content.Context;
Julia Reynolds83fa1072016-02-17 09:10:19 -050027import android.content.pm.ApplicationInfo;
Chris Wren333a61c2014-05-28 16:40:57 -040028import android.content.pm.PackageManager.NameNotFoundException;
29import android.content.res.Resources;
30import android.graphics.Bitmap;
Dan Sandlerd63f9322015-05-06 15:18:49 -040031import android.graphics.drawable.Icon;
John Spurlockbfa5dc42014-07-28 23:30:45 -040032import android.media.AudioAttributes;
Julia Reynolds83fa1072016-02-17 09:10:19 -050033import android.os.Build;
Chris Wrenda4bd202014-09-04 15:53:52 -040034import android.os.UserHandle;
Julia Reynolds5d25ee72015-11-20 15:38:20 -050035import android.service.notification.NotificationListenerService;
Chris Wren333a61c2014-05-28 16:40:57 -040036import android.service.notification.StatusBarNotification;
Julia Reynoldsf0f629f2016-02-25 09:34:04 -050037import android.util.Log;
38import android.util.Slog;
John Spurlockbfa5dc42014-07-28 23:30:45 -040039
Chris Wren1031c972014-07-23 13:11:45 +000040import com.android.internal.annotations.VisibleForTesting;
Chris Wren6650e572015-05-15 17:19:25 -040041import com.android.server.EventLogTags;
Chris Wren333a61c2014-05-28 16:40:57 -040042
43import java.io.PrintWriter;
44import java.lang.reflect.Array;
45import java.util.Arrays;
John Spurlock312d1d02014-07-08 10:24:57 -040046import java.util.Objects;
Chris Wren333a61c2014-05-28 16:40:57 -040047
48/**
49 * Holds data about notifications that should not be shared with the
50 * {@link android.service.notification.NotificationListenerService}s.
51 *
52 * <p>These objects should not be mutated unless the code is synchronized
53 * on {@link NotificationManagerService#mNotificationList}, and any
54 * modification should be followed by a sorting of that list.</p>
55 *
56 * <p>Is sortable by {@link NotificationComparator}.</p>
57 *
58 * {@hide}
59 */
60public final class NotificationRecord {
Julia Reynoldsf0f629f2016-02-25 09:34:04 -050061 static final String TAG = "NotificationRecord";
62 static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Chris Wren333a61c2014-05-28 16:40:57 -040063 final StatusBarNotification sbn;
Christoph Studer365e4c32014-09-18 20:35:36 +020064 final int mOriginalFlags;
Chris Wrenbdf33762015-12-04 15:50:51 -050065 private final Context mContext;
Christoph Studer365e4c32014-09-18 20:35:36 +020066
Chris Wren333a61c2014-05-28 16:40:57 -040067 NotificationUsageStats.SingleNotificationStats stats;
68 boolean isCanceled;
Amith Yamasanif47e51e2015-04-17 10:02:15 -070069 /** Whether the notification was seen by the user via one of the notification listeners. */
70 boolean mIsSeen;
Chris Wren333a61c2014-05-28 16:40:57 -040071
72 // These members are used by NotificationSignalExtractors
73 // to communicate with the ranking module.
74 private float mContactAffinity;
75 private boolean mRecentlyIntrusive;
76
77 // is this notification currently being intercepted by Zen Mode?
78 private boolean mIntercept;
Chris Wren333a61c2014-05-28 16:40:57 -040079
Christoph Studer52b7a5a2014-06-06 16:09:15 +020080 // The timestamp used for ranking.
81 private long mRankingTimeMs;
82
Chris Wren640e3872015-04-21 13:23:18 -040083 // The first post time, stable across updates.
84 private long mCreationTimeMs;
85
Chris Wren6650e572015-05-15 17:19:25 -040086 // The most recent visibility event.
87 private long mVisibleSinceMs;
88
89 // The most recent update time, or the creation time if no updates.
90 private long mUpdateTimeMs;
91
Chris Wrena3446562014-06-03 18:11:47 -040092 // Is this record an update of an old record?
93 public boolean isUpdate;
Chris Wren54bbef42014-07-09 18:37:56 -040094 private int mPackagePriority;
Chris Wrena3446562014-06-03 18:11:47 -040095
Chris Wren1031c972014-07-23 13:11:45 +000096 private int mAuthoritativeRank;
Christoph Studercd4adf82014-08-19 17:50:49 +020097 private String mGlobalSortKey;
Chris Wren3ad4e3a2014-09-02 17:23:51 -040098 private int mPackageVisibility;
Julia Reynoldsef37f282016-02-12 09:11:27 -050099 private int mUserImportance = IMPORTANCE_UNSPECIFIED;
Chris Wren47633422016-01-22 09:56:59 -0500100 private int mImportance = IMPORTANCE_UNSPECIFIED;
Chris Wrenbdf33762015-12-04 15:50:51 -0500101 private CharSequence mImportanceExplanation = null;
Chris Wren1031c972014-07-23 13:11:45 +0000102
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500103 private int mSuppressedVisualEffects = 0;
Julia Reynoldsef37f282016-02-12 09:11:27 -0500104 private String mUserExplanation;
Chris Wrenbdf33762015-12-04 15:50:51 -0500105 private String mPeopleExplanation;
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500106
Chris Wren1031c972014-07-23 13:11:45 +0000107 @VisibleForTesting
Chris Wrenbdf33762015-12-04 15:50:51 -0500108 public NotificationRecord(Context context, StatusBarNotification sbn)
Chris Wren333a61c2014-05-28 16:40:57 -0400109 {
110 this.sbn = sbn;
Christoph Studer365e4c32014-09-18 20:35:36 +0200111 mOriginalFlags = sbn.getNotification().flags;
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200112 mRankingTimeMs = calculateRankingTimeMs(0L);
Chris Wren640e3872015-04-21 13:23:18 -0400113 mCreationTimeMs = sbn.getPostTime();
Chris Wren6650e572015-05-15 17:19:25 -0400114 mUpdateTimeMs = mCreationTimeMs;
Chris Wrenbdf33762015-12-04 15:50:51 -0500115 mContext = context;
Chris Wrencdee8cd2016-01-25 17:10:30 -0500116 stats = new NotificationUsageStats.SingleNotificationStats();
Chris Wrenbdf33762015-12-04 15:50:51 -0500117 mImportance = defaultImportance();
118 }
119
120 private int defaultImportance() {
121 final Notification n = sbn.getNotification();
122 int importance = IMPORTANCE_DEFAULT;
123
124 // Migrate notification flags to scores
125 if (0 != (n.flags & Notification.FLAG_HIGH_PRIORITY)) {
126 n.priority = Notification.PRIORITY_MAX;
127 }
128
129 switch (n.priority) {
130 case Notification.PRIORITY_MIN:
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500131 importance = IMPORTANCE_MIN;
132 break;
Chris Wrenbdf33762015-12-04 15:50:51 -0500133 case Notification.PRIORITY_LOW:
134 importance = IMPORTANCE_LOW;
135 break;
136 case Notification.PRIORITY_DEFAULT:
137 importance = IMPORTANCE_DEFAULT;
138 break;
139 case Notification.PRIORITY_HIGH:
140 importance = IMPORTANCE_HIGH;
141 break;
142 case Notification.PRIORITY_MAX:
143 importance = IMPORTANCE_MAX;
144 break;
145 }
Chris Wrencdee8cd2016-01-25 17:10:30 -0500146 stats.requestedImportance = importance;
Chris Wrenbdf33762015-12-04 15:50:51 -0500147
148 boolean isNoisy = (n.defaults & Notification.DEFAULT_SOUND) != 0
149 || (n.defaults & Notification.DEFAULT_VIBRATE) != 0
150 || n.sound != null
151 || n.vibrate != null;
Chris Wrencdee8cd2016-01-25 17:10:30 -0500152 stats.isNoisy = isNoisy;
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500153
154 if (!isNoisy && importance > IMPORTANCE_LOW) {
155 importance = IMPORTANCE_LOW;
Chris Wrenbdf33762015-12-04 15:50:51 -0500156 }
Chris Wrenbdf33762015-12-04 15:50:51 -0500157
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500158 if (isNoisy) {
159 if (importance < IMPORTANCE_DEFAULT) {
160 importance = IMPORTANCE_DEFAULT;
Julia Reynolds83fa1072016-02-17 09:10:19 -0500161 }
Julia Reynolds83fa1072016-02-17 09:10:19 -0500162 }
163
Chris Wrenbdf33762015-12-04 15:50:51 -0500164 if (n.fullScreenIntent != null) {
165 importance = IMPORTANCE_MAX;
166 }
167
Chris Wrencdee8cd2016-01-25 17:10:30 -0500168 stats.naturalImportance = importance;
Chris Wrenbdf33762015-12-04 15:50:51 -0500169 return importance;
Chris Wren333a61c2014-05-28 16:40:57 -0400170 }
171
172 // copy any notes that the ranking system may have made before the update
173 public void copyRankingInformation(NotificationRecord previous) {
174 mContactAffinity = previous.mContactAffinity;
175 mRecentlyIntrusive = previous.mRecentlyIntrusive;
Chris Wren54bbef42014-07-09 18:37:56 -0400176 mPackagePriority = previous.mPackagePriority;
Chris Wren3ad4e3a2014-09-02 17:23:51 -0400177 mPackageVisibility = previous.mPackageVisibility;
Chris Wren333a61c2014-05-28 16:40:57 -0400178 mIntercept = previous.mIntercept;
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200179 mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
Chris Wren640e3872015-04-21 13:23:18 -0400180 mCreationTimeMs = previous.mCreationTimeMs;
Chris Wren6650e572015-05-15 17:19:25 -0400181 mVisibleSinceMs = previous.mVisibleSinceMs;
Julia Reynoldsef37f282016-02-12 09:11:27 -0500182 mUserImportance = previous.mUserImportance;
Chris Wrenbdf33762015-12-04 15:50:51 -0500183 mImportance = previous.mImportance;
184 mImportanceExplanation = previous.mImportanceExplanation;
Christoph Studercd4adf82014-08-19 17:50:49 +0200185 // Don't copy mGlobalSortKey, recompute it.
Chris Wren333a61c2014-05-28 16:40:57 -0400186 }
187
188 public Notification getNotification() { return sbn.getNotification(); }
189 public int getFlags() { return sbn.getNotification().flags; }
Chris Wrenda4bd202014-09-04 15:53:52 -0400190 public UserHandle getUser() { return sbn.getUser(); }
Chris Wren333a61c2014-05-28 16:40:57 -0400191 public String getKey() { return sbn.getKey(); }
Chris Wrenda4bd202014-09-04 15:53:52 -0400192 /** @deprecated Use {@link #getUser()} instead. */
193 public int getUserId() { return sbn.getUserId(); }
Chris Wren333a61c2014-05-28 16:40:57 -0400194
Dan Sandlera1770312015-07-10 13:59:29 -0400195 void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
Chris Wren333a61c2014-05-28 16:40:57 -0400196 final Notification notification = sbn.getNotification();
Dan Sandlerd63f9322015-05-06 15:18:49 -0400197 final Icon icon = notification.getSmallIcon();
198 String iconStr = String.valueOf(icon);
199 if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
200 iconStr += " / " + idDebugString(baseContext, icon.getResPackage(), icon.getResId());
201 }
Chris Wren333a61c2014-05-28 16:40:57 -0400202 pw.println(prefix + this);
203 pw.println(prefix + " uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
Dan Sandlerd63f9322015-05-06 15:18:49 -0400204 pw.println(prefix + " icon=" + iconStr);
Chris Wrenbdf33762015-12-04 15:50:51 -0500205 pw.println(prefix + " pri=" + notification.priority);
Chris Wren333a61c2014-05-28 16:40:57 -0400206 pw.println(prefix + " key=" + sbn.getKey());
Amith Yamasani24bd0be2015-04-28 10:28:09 -0700207 pw.println(prefix + " seen=" + mIsSeen);
Chris Wren1031c972014-07-23 13:11:45 +0000208 pw.println(prefix + " groupKey=" + getGroupKey());
Chris Wren333a61c2014-05-28 16:40:57 -0400209 pw.println(prefix + " contentIntent=" + notification.contentIntent);
210 pw.println(prefix + " deleteIntent=" + notification.deleteIntent);
211 pw.println(prefix + " tickerText=" + notification.tickerText);
212 pw.println(prefix + " contentView=" + notification.contentView);
213 pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x",
214 notification.defaults, notification.flags));
215 pw.println(prefix + " sound=" + notification.sound);
John Spurlockbfa5dc42014-07-28 23:30:45 -0400216 pw.println(prefix + " audioStreamType=" + notification.audioStreamType);
217 pw.println(prefix + " audioAttributes=" + notification.audioAttributes);
Chris Wren333a61c2014-05-28 16:40:57 -0400218 pw.println(prefix + String.format(" color=0x%08x", notification.color));
219 pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate));
220 pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d",
221 notification.ledARGB, notification.ledOnMS, notification.ledOffMS));
222 if (notification.actions != null && notification.actions.length > 0) {
223 pw.println(prefix + " actions={");
224 final int N = notification.actions.length;
225 for (int i=0; i<N; i++) {
226 final Notification.Action action = notification.actions[i];
Chris Wren1ac52a92016-02-24 14:54:52 -0500227 if (action != null) {
228 pw.println(String.format("%s [%d] \"%s\" -> %s",
229 prefix,
230 i,
231 action.title,
232 action.actionIntent == null ? "null" : action.actionIntent.toString()
233 ));
234 }
Chris Wren333a61c2014-05-28 16:40:57 -0400235 }
236 pw.println(prefix + " }");
237 }
238 if (notification.extras != null && notification.extras.size() > 0) {
239 pw.println(prefix + " extras={");
240 for (String key : notification.extras.keySet()) {
241 pw.print(prefix + " " + key + "=");
242 Object val = notification.extras.get(key);
243 if (val == null) {
244 pw.println("null");
245 } else {
246 pw.print(val.getClass().getSimpleName());
Dan Sandlera1770312015-07-10 13:59:29 -0400247 if (redact && (val instanceof CharSequence || val instanceof String)) {
Chris Wren333a61c2014-05-28 16:40:57 -0400248 // redact contents from bugreports
249 } else if (val instanceof Bitmap) {
250 pw.print(String.format(" (%dx%d)",
251 ((Bitmap) val).getWidth(),
252 ((Bitmap) val).getHeight()));
253 } else if (val.getClass().isArray()) {
254 final int N = Array.getLength(val);
Dan Sandlera1770312015-07-10 13:59:29 -0400255 pw.print(" (" + N + ")");
256 if (!redact) {
257 for (int j=0; j<N; j++) {
258 pw.println();
259 pw.print(String.format("%s [%d] %s",
260 prefix, j, String.valueOf(Array.get(val, j))));
261 }
262 }
Chris Wren333a61c2014-05-28 16:40:57 -0400263 } else {
264 pw.print(" (" + String.valueOf(val) + ")");
265 }
266 pw.println();
267 }
268 }
269 pw.println(prefix + " }");
270 }
271 pw.println(prefix + " stats=" + stats.toString());
272 pw.println(prefix + " mContactAffinity=" + mContactAffinity);
273 pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive);
Chris Wren54bbef42014-07-09 18:37:56 -0400274 pw.println(prefix + " mPackagePriority=" + mPackagePriority);
Chris Wren3ad4e3a2014-09-02 17:23:51 -0400275 pw.println(prefix + " mPackageVisibility=" + mPackageVisibility);
Julia Reynoldsef37f282016-02-12 09:11:27 -0500276 pw.println(prefix + " mUserImportance="
277 + NotificationListenerService.Ranking.importanceToString(mUserImportance));
Chris Wrenbdf33762015-12-04 15:50:51 -0500278 pw.println(prefix + " mImportance="
279 + NotificationListenerService.Ranking.importanceToString(mImportance));
280 pw.println(prefix + " mImportanceExplanation=" + mImportanceExplanation);
Chris Wren333a61c2014-05-28 16:40:57 -0400281 pw.println(prefix + " mIntercept=" + mIntercept);
Christoph Studercd4adf82014-08-19 17:50:49 +0200282 pw.println(prefix + " mGlobalSortKey=" + mGlobalSortKey);
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200283 pw.println(prefix + " mRankingTimeMs=" + mRankingTimeMs);
Chris Wren640e3872015-04-21 13:23:18 -0400284 pw.println(prefix + " mCreationTimeMs=" + mCreationTimeMs);
Chris Wren6650e572015-05-15 17:19:25 -0400285 pw.println(prefix + " mVisibleSinceMs=" + mVisibleSinceMs);
286 pw.println(prefix + " mUpdateTimeMs=" + mUpdateTimeMs);
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500287 pw.println(prefix + " mSuppressedVisualEffects= " + mSuppressedVisualEffects);
Chris Wren333a61c2014-05-28 16:40:57 -0400288 }
289
290
291 static String idDebugString(Context baseContext, String packageName, int id) {
292 Context c;
293
294 if (packageName != null) {
295 try {
296 c = baseContext.createPackageContext(packageName, 0);
297 } catch (NameNotFoundException e) {
298 c = baseContext;
299 }
300 } else {
301 c = baseContext;
302 }
303
304 Resources r = c.getResources();
305 try {
306 return r.getResourceName(id);
307 } catch (Resources.NotFoundException e) {
308 return "<name unknown>";
309 }
310 }
311
312 @Override
313 public final String toString() {
314 return String.format(
Chris Wrenbdf33762015-12-04 15:50:51 -0500315 "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s: %s)",
Chris Wren333a61c2014-05-28 16:40:57 -0400316 System.identityHashCode(this),
317 this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
Chris Wrenbdf33762015-12-04 15:50:51 -0500318 this.sbn.getTag(), this.mImportance, this.sbn.getKey(),
Chris Wren333a61c2014-05-28 16:40:57 -0400319 this.sbn.getNotification());
320 }
321
322 public void setContactAffinity(float contactAffinity) {
323 mContactAffinity = contactAffinity;
Chris Wrenbdf33762015-12-04 15:50:51 -0500324 if (mImportance < IMPORTANCE_DEFAULT &&
325 mContactAffinity > ValidateNotificationPeople.VALID_CONTACT) {
326 setImportance(IMPORTANCE_DEFAULT, getPeopleExplanation());
327 }
Chris Wren333a61c2014-05-28 16:40:57 -0400328 }
329
330 public float getContactAffinity() {
331 return mContactAffinity;
332 }
333
John Spurlock1d881a12015-03-18 19:21:54 -0400334 public void setRecentlyIntrusive(boolean recentlyIntrusive) {
Chris Wren333a61c2014-05-28 16:40:57 -0400335 mRecentlyIntrusive = recentlyIntrusive;
336 }
337
338 public boolean isRecentlyIntrusive() {
339 return mRecentlyIntrusive;
340 }
341
Chris Wren54bbef42014-07-09 18:37:56 -0400342 public void setPackagePriority(int packagePriority) {
John Spurlock6ac5f8d2014-07-18 11:27:54 -0400343 mPackagePriority = packagePriority;
Chris Wren54bbef42014-07-09 18:37:56 -0400344 }
345
346 public int getPackagePriority() {
347 return mPackagePriority;
348 }
349
Chris Wren3ad4e3a2014-09-02 17:23:51 -0400350 public void setPackageVisibilityOverride(int packageVisibility) {
351 mPackageVisibility = packageVisibility;
352 }
353
354 public int getPackageVisibilityOverride() {
355 return mPackageVisibility;
356 }
357
Julia Reynoldsef37f282016-02-12 09:11:27 -0500358 public void setUserImportance(int importance) {
359 mUserImportance = importance;
360 applyUserImportance();
Chris Wrenbdf33762015-12-04 15:50:51 -0500361 }
362
Julia Reynoldsef37f282016-02-12 09:11:27 -0500363 private String getUserExplanation() {
364 if (mUserExplanation == null) {
365 mUserExplanation =
366 mContext.getString(com.android.internal.R.string.importance_from_user);
Chris Wrenbdf33762015-12-04 15:50:51 -0500367 }
Julia Reynoldsef37f282016-02-12 09:11:27 -0500368 return mUserExplanation;
Chris Wrenbdf33762015-12-04 15:50:51 -0500369 }
370
371 private String getPeopleExplanation() {
372 if (mPeopleExplanation == null) {
373 mPeopleExplanation =
374 mContext.getString(com.android.internal.R.string.importance_from_person);
375 }
376 return mPeopleExplanation;
377 }
378
Julia Reynoldsef37f282016-02-12 09:11:27 -0500379 private void applyUserImportance() {
380 if (mUserImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
381 mImportance = mUserImportance;
382 mImportanceExplanation = getUserExplanation();
Julia Reynolds5d25ee72015-11-20 15:38:20 -0500383 }
384 }
385
Julia Reynoldsef37f282016-02-12 09:11:27 -0500386 public int getUserImportance() {
387 return mUserImportance;
Julia Reynolds5d25ee72015-11-20 15:38:20 -0500388 }
389
Chris Wrenbdf33762015-12-04 15:50:51 -0500390 public void setImportance(int importance, CharSequence explanation) {
391 if (importance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
392 mImportance = importance;
393 mImportanceExplanation = explanation;
394 }
Julia Reynoldsef37f282016-02-12 09:11:27 -0500395 applyUserImportance();
Chris Wrenbdf33762015-12-04 15:50:51 -0500396 }
397
398 public int getImportance() {
399 return mImportance;
400 }
401
402 public CharSequence getImportanceExplanation() {
403 return mImportanceExplanation;
404 }
405
Chris Wren333a61c2014-05-28 16:40:57 -0400406 public boolean setIntercepted(boolean intercept) {
407 mIntercept = intercept;
408 return mIntercept;
409 }
410
411 public boolean isIntercepted() {
412 return mIntercept;
413 }
414
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500415 public void setSuppressedVisualEffects(int effects) {
416 mSuppressedVisualEffects = effects;
417 }
418
419 public int getSuppressedVisualEffects() {
420 return mSuppressedVisualEffects;
421 }
422
John Spurlock312d1d02014-07-08 10:24:57 -0400423 public boolean isCategory(String category) {
John Spurlockbfa5dc42014-07-28 23:30:45 -0400424 return Objects.equals(getNotification().category, category);
425 }
426
427 public boolean isAudioStream(int stream) {
428 return getNotification().audioStreamType == stream;
429 }
430
431 public boolean isAudioAttributesUsage(int usage) {
432 final AudioAttributes attributes = getNotification().audioAttributes;
433 return attributes != null && attributes.getUsage() == usage;
John Spurlock312d1d02014-07-08 10:24:57 -0400434 }
435
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200436 /**
437 * Returns the timestamp to use for time-based sorting in the ranker.
438 */
439 public long getRankingTimeMs() {
440 return mRankingTimeMs;
441 }
442
443 /**
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400444 * @param now this current time in milliseconds.
445 * @returns the number of milliseconds since the most recent update, or the post time if none.
Chris Wren6650e572015-05-15 17:19:25 -0400446 */
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400447 public int getFreshnessMs(long now) {
448 return (int) (now - mUpdateTimeMs);
Chris Wren6650e572015-05-15 17:19:25 -0400449 }
450
451 /**
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400452 * @param now this current time in milliseconds.
453 * @returns the number of milliseconds since the the first post, ignoring updates.
Chris Wren640e3872015-04-21 13:23:18 -0400454 */
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400455 public int getLifespanMs(long now) {
456 return (int) (now - mCreationTimeMs);
Chris Wren640e3872015-04-21 13:23:18 -0400457 }
458
459 /**
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400460 * @param now this current time in milliseconds.
461 * @returns the number of milliseconds since the most recent visibility event, or 0 if never.
Chris Wren6650e572015-05-15 17:19:25 -0400462 */
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400463 public int getExposureMs(long now) {
464 return mVisibleSinceMs == 0 ? 0 : (int) (now - mVisibleSinceMs);
Chris Wren6650e572015-05-15 17:19:25 -0400465 }
466
467 /**
468 * Set the visibility of the notification.
469 */
Chris Wrend1dbc922015-06-19 17:51:16 -0400470 public void setVisibility(boolean visible, int rank) {
Chris Wren6650e572015-05-15 17:19:25 -0400471 final long now = System.currentTimeMillis();
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400472 mVisibleSinceMs = visible ? now : mVisibleSinceMs;
Chris Wren6650e572015-05-15 17:19:25 -0400473 stats.onVisibilityChanged(visible);
474 EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
475 (int) (now - mCreationTimeMs),
Chris Wrend1dbc922015-06-19 17:51:16 -0400476 (int) (now - mUpdateTimeMs),
477 0, // exposure time
478 rank);
Chris Wren6650e572015-05-15 17:19:25 -0400479 }
480
481 /**
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200482 * @param previousRankingTimeMs for updated notifications, {@link #getRankingTimeMs()}
483 * of the previous notification record, 0 otherwise
484 */
485 private long calculateRankingTimeMs(long previousRankingTimeMs) {
486 Notification n = getNotification();
487 // Take developer provided 'when', unless it's in the future.
488 if (n.when != 0 && n.when <= sbn.getPostTime()) {
489 return n.when;
490 }
491 // If we've ranked a previous instance with a timestamp, inherit it. This case is
492 // important in order to have ranking stability for updating notifications.
493 if (previousRankingTimeMs > 0) {
494 return previousRankingTimeMs;
495 }
496 return sbn.getPostTime();
497 }
Chris Wren1031c972014-07-23 13:11:45 +0000498
Christoph Studercd4adf82014-08-19 17:50:49 +0200499 public void setGlobalSortKey(String globalSortKey) {
500 mGlobalSortKey = globalSortKey;
Chris Wren1031c972014-07-23 13:11:45 +0000501 }
502
Christoph Studercd4adf82014-08-19 17:50:49 +0200503 public String getGlobalSortKey() {
504 return mGlobalSortKey;
Chris Wren1031c972014-07-23 13:11:45 +0000505 }
506
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700507 /** Check if any of the listeners have marked this notification as seen by the user. */
508 public boolean isSeen() {
509 return mIsSeen;
510 }
511
512 /** Mark the notification as seen by the user. */
513 public void setSeen() {
514 mIsSeen = true;
515 }
516
Chris Wren1031c972014-07-23 13:11:45 +0000517 public void setAuthoritativeRank(int authoritativeRank) {
518 mAuthoritativeRank = authoritativeRank;
519 }
520
521 public int getAuthoritativeRank() {
522 return mAuthoritativeRank;
523 }
524
525 public String getGroupKey() {
526 return sbn.getGroupKey();
527 }
Chris Wren47633422016-01-22 09:56:59 -0500528
529 public boolean isImportanceFromUser() {
Julia Reynoldsef37f282016-02-12 09:11:27 -0500530 return mImportance == mUserImportance;
Chris Wren47633422016-01-22 09:56:59 -0500531 }
Chris Wren333a61c2014-05-28 16:40:57 -0400532}