blob: 7c89e9f0ba934680e54a3ba4f1232556b35e33ff [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;
27import android.content.pm.PackageManager.NameNotFoundException;
28import android.content.res.Resources;
29import android.graphics.Bitmap;
Dan Sandlerd63f9322015-05-06 15:18:49 -040030import android.graphics.drawable.Icon;
John Spurlockbfa5dc42014-07-28 23:30:45 -040031import android.media.AudioAttributes;
Chris Wrenda4bd202014-09-04 15:53:52 -040032import android.os.UserHandle;
Julia Reynolds5d25ee72015-11-20 15:38:20 -050033import android.service.notification.NotificationListenerService;
Chris Wren333a61c2014-05-28 16:40:57 -040034import android.service.notification.StatusBarNotification;
Julia Reynoldsf0f629f2016-02-25 09:34:04 -050035import android.util.Log;
John Spurlockbfa5dc42014-07-28 23:30:45 -040036
Chris Wren1031c972014-07-23 13:11:45 +000037import com.android.internal.annotations.VisibleForTesting;
Chris Wren6650e572015-05-15 17:19:25 -040038import com.android.server.EventLogTags;
Chris Wren333a61c2014-05-28 16:40:57 -040039
40import java.io.PrintWriter;
41import java.lang.reflect.Array;
42import java.util.Arrays;
John Spurlock312d1d02014-07-08 10:24:57 -040043import java.util.Objects;
Chris Wren333a61c2014-05-28 16:40:57 -040044
45/**
46 * Holds data about notifications that should not be shared with the
47 * {@link android.service.notification.NotificationListenerService}s.
48 *
49 * <p>These objects should not be mutated unless the code is synchronized
50 * on {@link NotificationManagerService#mNotificationList}, and any
51 * modification should be followed by a sorting of that list.</p>
52 *
53 * <p>Is sortable by {@link NotificationComparator}.</p>
54 *
55 * {@hide}
56 */
57public final class NotificationRecord {
Julia Reynoldsf0f629f2016-02-25 09:34:04 -050058 static final String TAG = "NotificationRecord";
59 static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Chris Wren333a61c2014-05-28 16:40:57 -040060 final StatusBarNotification sbn;
Christoph Studer365e4c32014-09-18 20:35:36 +020061 final int mOriginalFlags;
Chris Wrenbdf33762015-12-04 15:50:51 -050062 private final Context mContext;
Christoph Studer365e4c32014-09-18 20:35:36 +020063
Chris Wren333a61c2014-05-28 16:40:57 -040064 NotificationUsageStats.SingleNotificationStats stats;
65 boolean isCanceled;
Amith Yamasanif47e51e2015-04-17 10:02:15 -070066 /** Whether the notification was seen by the user via one of the notification listeners. */
67 boolean mIsSeen;
Chris Wren333a61c2014-05-28 16:40:57 -040068
69 // These members are used by NotificationSignalExtractors
70 // to communicate with the ranking module.
71 private float mContactAffinity;
72 private boolean mRecentlyIntrusive;
73
74 // is this notification currently being intercepted by Zen Mode?
75 private boolean mIntercept;
Chris Wren333a61c2014-05-28 16:40:57 -040076
Christoph Studer52b7a5a2014-06-06 16:09:15 +020077 // The timestamp used for ranking.
78 private long mRankingTimeMs;
79
Chris Wren640e3872015-04-21 13:23:18 -040080 // The first post time, stable across updates.
81 private long mCreationTimeMs;
82
Chris Wren6650e572015-05-15 17:19:25 -040083 // The most recent visibility event.
84 private long mVisibleSinceMs;
85
86 // The most recent update time, or the creation time if no updates.
87 private long mUpdateTimeMs;
88
Chris Wrena3446562014-06-03 18:11:47 -040089 // Is this record an update of an old record?
90 public boolean isUpdate;
Chris Wren54bbef42014-07-09 18:37:56 -040091 private int mPackagePriority;
Chris Wrena3446562014-06-03 18:11:47 -040092
Chris Wren1031c972014-07-23 13:11:45 +000093 private int mAuthoritativeRank;
Christoph Studercd4adf82014-08-19 17:50:49 +020094 private String mGlobalSortKey;
Chris Wren3ad4e3a2014-09-02 17:23:51 -040095 private int mPackageVisibility;
Julia Reynoldsef37f282016-02-12 09:11:27 -050096 private int mUserImportance = IMPORTANCE_UNSPECIFIED;
Chris Wren47633422016-01-22 09:56:59 -050097 private int mImportance = IMPORTANCE_UNSPECIFIED;
Chris Wrenbdf33762015-12-04 15:50:51 -050098 private CharSequence mImportanceExplanation = null;
Chris Wren1031c972014-07-23 13:11:45 +000099
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500100 private int mSuppressedVisualEffects = 0;
Julia Reynoldsef37f282016-02-12 09:11:27 -0500101 private String mUserExplanation;
Chris Wrenbdf33762015-12-04 15:50:51 -0500102 private String mPeopleExplanation;
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500103
Chris Wren1031c972014-07-23 13:11:45 +0000104 @VisibleForTesting
Chris Wrenbdf33762015-12-04 15:50:51 -0500105 public NotificationRecord(Context context, StatusBarNotification sbn)
Chris Wren333a61c2014-05-28 16:40:57 -0400106 {
107 this.sbn = sbn;
Christoph Studer365e4c32014-09-18 20:35:36 +0200108 mOriginalFlags = sbn.getNotification().flags;
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200109 mRankingTimeMs = calculateRankingTimeMs(0L);
Chris Wren640e3872015-04-21 13:23:18 -0400110 mCreationTimeMs = sbn.getPostTime();
Chris Wren6650e572015-05-15 17:19:25 -0400111 mUpdateTimeMs = mCreationTimeMs;
Chris Wrenbdf33762015-12-04 15:50:51 -0500112 mContext = context;
Chris Wrencdee8cd2016-01-25 17:10:30 -0500113 stats = new NotificationUsageStats.SingleNotificationStats();
Chris Wrenbdf33762015-12-04 15:50:51 -0500114 mImportance = defaultImportance();
115 }
116
117 private int defaultImportance() {
118 final Notification n = sbn.getNotification();
119 int importance = IMPORTANCE_DEFAULT;
120
121 // Migrate notification flags to scores
122 if (0 != (n.flags & Notification.FLAG_HIGH_PRIORITY)) {
123 n.priority = Notification.PRIORITY_MAX;
124 }
125
126 switch (n.priority) {
127 case Notification.PRIORITY_MIN:
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500128 importance = IMPORTANCE_MIN;
129 break;
Chris Wrenbdf33762015-12-04 15:50:51 -0500130 case Notification.PRIORITY_LOW:
131 importance = IMPORTANCE_LOW;
132 break;
133 case Notification.PRIORITY_DEFAULT:
134 importance = IMPORTANCE_DEFAULT;
135 break;
136 case Notification.PRIORITY_HIGH:
137 importance = IMPORTANCE_HIGH;
138 break;
139 case Notification.PRIORITY_MAX:
140 importance = IMPORTANCE_MAX;
141 break;
142 }
Chris Wrencdee8cd2016-01-25 17:10:30 -0500143 stats.requestedImportance = importance;
Chris Wrenbdf33762015-12-04 15:50:51 -0500144
145 boolean isNoisy = (n.defaults & Notification.DEFAULT_SOUND) != 0
146 || (n.defaults & Notification.DEFAULT_VIBRATE) != 0
147 || n.sound != null
148 || n.vibrate != null;
Chris Wrencdee8cd2016-01-25 17:10:30 -0500149 stats.isNoisy = isNoisy;
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500150
151 if (!isNoisy && importance > IMPORTANCE_LOW) {
152 importance = IMPORTANCE_LOW;
Chris Wrenbdf33762015-12-04 15:50:51 -0500153 }
Chris Wrenbdf33762015-12-04 15:50:51 -0500154
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500155 if (isNoisy) {
156 if (importance < IMPORTANCE_DEFAULT) {
157 importance = IMPORTANCE_DEFAULT;
Julia Reynolds83fa1072016-02-17 09:10:19 -0500158 }
Julia Reynolds83fa1072016-02-17 09:10:19 -0500159 }
160
Chris Wrenbdf33762015-12-04 15:50:51 -0500161 if (n.fullScreenIntent != null) {
162 importance = IMPORTANCE_MAX;
163 }
164
Chris Wrencdee8cd2016-01-25 17:10:30 -0500165 stats.naturalImportance = importance;
Chris Wrenbdf33762015-12-04 15:50:51 -0500166 return importance;
Chris Wren333a61c2014-05-28 16:40:57 -0400167 }
168
169 // copy any notes that the ranking system may have made before the update
170 public void copyRankingInformation(NotificationRecord previous) {
171 mContactAffinity = previous.mContactAffinity;
172 mRecentlyIntrusive = previous.mRecentlyIntrusive;
Chris Wren54bbef42014-07-09 18:37:56 -0400173 mPackagePriority = previous.mPackagePriority;
Chris Wren3ad4e3a2014-09-02 17:23:51 -0400174 mPackageVisibility = previous.mPackageVisibility;
Chris Wren333a61c2014-05-28 16:40:57 -0400175 mIntercept = previous.mIntercept;
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200176 mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
Chris Wren640e3872015-04-21 13:23:18 -0400177 mCreationTimeMs = previous.mCreationTimeMs;
Chris Wren6650e572015-05-15 17:19:25 -0400178 mVisibleSinceMs = previous.mVisibleSinceMs;
Selim Cinek5b03ce92016-05-18 15:16:58 -0700179 if (previous.sbn.getOverrideGroupKey() != null && !sbn.isAppGroup()) {
Chris Wren8a1638f2016-05-02 16:19:14 -0400180 sbn.setOverrideGroupKey(previous.sbn.getOverrideGroupKey());
181 }
Chris Wren1f602dc2016-04-11 10:33:46 -0400182 // Don't copy importance information or mGlobalSortKey, recompute them.
Chris Wren333a61c2014-05-28 16:40:57 -0400183 }
184
185 public Notification getNotification() { return sbn.getNotification(); }
186 public int getFlags() { return sbn.getNotification().flags; }
Chris Wrenda4bd202014-09-04 15:53:52 -0400187 public UserHandle getUser() { return sbn.getUser(); }
Chris Wren333a61c2014-05-28 16:40:57 -0400188 public String getKey() { return sbn.getKey(); }
Chris Wrenda4bd202014-09-04 15:53:52 -0400189 /** @deprecated Use {@link #getUser()} instead. */
190 public int getUserId() { return sbn.getUserId(); }
Chris Wren333a61c2014-05-28 16:40:57 -0400191
Dan Sandlera1770312015-07-10 13:59:29 -0400192 void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
Chris Wren333a61c2014-05-28 16:40:57 -0400193 final Notification notification = sbn.getNotification();
Dan Sandlerd63f9322015-05-06 15:18:49 -0400194 final Icon icon = notification.getSmallIcon();
195 String iconStr = String.valueOf(icon);
196 if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
197 iconStr += " / " + idDebugString(baseContext, icon.getResPackage(), icon.getResId());
198 }
Chris Wren333a61c2014-05-28 16:40:57 -0400199 pw.println(prefix + this);
200 pw.println(prefix + " uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
Dan Sandlerd63f9322015-05-06 15:18:49 -0400201 pw.println(prefix + " icon=" + iconStr);
Chris Wrenbdf33762015-12-04 15:50:51 -0500202 pw.println(prefix + " pri=" + notification.priority);
Chris Wren333a61c2014-05-28 16:40:57 -0400203 pw.println(prefix + " key=" + sbn.getKey());
Amith Yamasani24bd0be2015-04-28 10:28:09 -0700204 pw.println(prefix + " seen=" + mIsSeen);
Chris Wren1031c972014-07-23 13:11:45 +0000205 pw.println(prefix + " groupKey=" + getGroupKey());
Chris Wren333a61c2014-05-28 16:40:57 -0400206 pw.println(prefix + " contentIntent=" + notification.contentIntent);
207 pw.println(prefix + " deleteIntent=" + notification.deleteIntent);
208 pw.println(prefix + " tickerText=" + notification.tickerText);
209 pw.println(prefix + " contentView=" + notification.contentView);
210 pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x",
211 notification.defaults, notification.flags));
212 pw.println(prefix + " sound=" + notification.sound);
John Spurlockbfa5dc42014-07-28 23:30:45 -0400213 pw.println(prefix + " audioStreamType=" + notification.audioStreamType);
214 pw.println(prefix + " audioAttributes=" + notification.audioAttributes);
Chris Wren333a61c2014-05-28 16:40:57 -0400215 pw.println(prefix + String.format(" color=0x%08x", notification.color));
216 pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate));
217 pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d",
218 notification.ledARGB, notification.ledOnMS, notification.ledOffMS));
219 if (notification.actions != null && notification.actions.length > 0) {
220 pw.println(prefix + " actions={");
221 final int N = notification.actions.length;
222 for (int i=0; i<N; i++) {
223 final Notification.Action action = notification.actions[i];
Chris Wren1ac52a92016-02-24 14:54:52 -0500224 if (action != null) {
225 pw.println(String.format("%s [%d] \"%s\" -> %s",
226 prefix,
227 i,
228 action.title,
229 action.actionIntent == null ? "null" : action.actionIntent.toString()
230 ));
231 }
Chris Wren333a61c2014-05-28 16:40:57 -0400232 }
233 pw.println(prefix + " }");
234 }
235 if (notification.extras != null && notification.extras.size() > 0) {
236 pw.println(prefix + " extras={");
237 for (String key : notification.extras.keySet()) {
238 pw.print(prefix + " " + key + "=");
239 Object val = notification.extras.get(key);
240 if (val == null) {
241 pw.println("null");
242 } else {
243 pw.print(val.getClass().getSimpleName());
Dan Sandlera1770312015-07-10 13:59:29 -0400244 if (redact && (val instanceof CharSequence || val instanceof String)) {
Chris Wren333a61c2014-05-28 16:40:57 -0400245 // redact contents from bugreports
246 } else if (val instanceof Bitmap) {
247 pw.print(String.format(" (%dx%d)",
248 ((Bitmap) val).getWidth(),
249 ((Bitmap) val).getHeight()));
250 } else if (val.getClass().isArray()) {
251 final int N = Array.getLength(val);
Dan Sandlera1770312015-07-10 13:59:29 -0400252 pw.print(" (" + N + ")");
253 if (!redact) {
254 for (int j=0; j<N; j++) {
255 pw.println();
256 pw.print(String.format("%s [%d] %s",
257 prefix, j, String.valueOf(Array.get(val, j))));
258 }
259 }
Chris Wren333a61c2014-05-28 16:40:57 -0400260 } else {
261 pw.print(" (" + String.valueOf(val) + ")");
262 }
263 pw.println();
264 }
265 }
266 pw.println(prefix + " }");
267 }
268 pw.println(prefix + " stats=" + stats.toString());
269 pw.println(prefix + " mContactAffinity=" + mContactAffinity);
270 pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive);
Chris Wren54bbef42014-07-09 18:37:56 -0400271 pw.println(prefix + " mPackagePriority=" + mPackagePriority);
Chris Wren3ad4e3a2014-09-02 17:23:51 -0400272 pw.println(prefix + " mPackageVisibility=" + mPackageVisibility);
Julia Reynoldsef37f282016-02-12 09:11:27 -0500273 pw.println(prefix + " mUserImportance="
274 + NotificationListenerService.Ranking.importanceToString(mUserImportance));
Chris Wrenbdf33762015-12-04 15:50:51 -0500275 pw.println(prefix + " mImportance="
276 + NotificationListenerService.Ranking.importanceToString(mImportance));
277 pw.println(prefix + " mImportanceExplanation=" + mImportanceExplanation);
Chris Wren333a61c2014-05-28 16:40:57 -0400278 pw.println(prefix + " mIntercept=" + mIntercept);
Christoph Studercd4adf82014-08-19 17:50:49 +0200279 pw.println(prefix + " mGlobalSortKey=" + mGlobalSortKey);
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200280 pw.println(prefix + " mRankingTimeMs=" + mRankingTimeMs);
Chris Wren640e3872015-04-21 13:23:18 -0400281 pw.println(prefix + " mCreationTimeMs=" + mCreationTimeMs);
Chris Wren6650e572015-05-15 17:19:25 -0400282 pw.println(prefix + " mVisibleSinceMs=" + mVisibleSinceMs);
283 pw.println(prefix + " mUpdateTimeMs=" + mUpdateTimeMs);
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500284 pw.println(prefix + " mSuppressedVisualEffects= " + mSuppressedVisualEffects);
Chris Wren333a61c2014-05-28 16:40:57 -0400285 }
286
287
288 static String idDebugString(Context baseContext, String packageName, int id) {
289 Context c;
290
291 if (packageName != null) {
292 try {
293 c = baseContext.createPackageContext(packageName, 0);
294 } catch (NameNotFoundException e) {
295 c = baseContext;
296 }
297 } else {
298 c = baseContext;
299 }
300
301 Resources r = c.getResources();
302 try {
303 return r.getResourceName(id);
304 } catch (Resources.NotFoundException e) {
305 return "<name unknown>";
306 }
307 }
308
309 @Override
310 public final String toString() {
311 return String.format(
Chris Wrenbdf33762015-12-04 15:50:51 -0500312 "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s: %s)",
Chris Wren333a61c2014-05-28 16:40:57 -0400313 System.identityHashCode(this),
314 this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
Chris Wrenbdf33762015-12-04 15:50:51 -0500315 this.sbn.getTag(), this.mImportance, this.sbn.getKey(),
Chris Wren333a61c2014-05-28 16:40:57 -0400316 this.sbn.getNotification());
317 }
318
319 public void setContactAffinity(float contactAffinity) {
320 mContactAffinity = contactAffinity;
Chris Wrenbdf33762015-12-04 15:50:51 -0500321 if (mImportance < IMPORTANCE_DEFAULT &&
Chris Wrenc977f812016-06-13 21:24:53 +0000322 mContactAffinity > ValidateNotificationPeople.VALID_CONTACT) {
Chris Wrenbdf33762015-12-04 15:50:51 -0500323 setImportance(IMPORTANCE_DEFAULT, getPeopleExplanation());
324 }
Chris Wren333a61c2014-05-28 16:40:57 -0400325 }
326
327 public float getContactAffinity() {
328 return mContactAffinity;
329 }
330
John Spurlock1d881a12015-03-18 19:21:54 -0400331 public void setRecentlyIntrusive(boolean recentlyIntrusive) {
Chris Wren333a61c2014-05-28 16:40:57 -0400332 mRecentlyIntrusive = recentlyIntrusive;
333 }
334
335 public boolean isRecentlyIntrusive() {
336 return mRecentlyIntrusive;
337 }
338
Chris Wren54bbef42014-07-09 18:37:56 -0400339 public void setPackagePriority(int packagePriority) {
John Spurlock6ac5f8d2014-07-18 11:27:54 -0400340 mPackagePriority = packagePriority;
Chris Wren54bbef42014-07-09 18:37:56 -0400341 }
342
343 public int getPackagePriority() {
344 return mPackagePriority;
345 }
346
Chris Wren3ad4e3a2014-09-02 17:23:51 -0400347 public void setPackageVisibilityOverride(int packageVisibility) {
348 mPackageVisibility = packageVisibility;
349 }
350
351 public int getPackageVisibilityOverride() {
352 return mPackageVisibility;
353 }
354
Julia Reynoldsef37f282016-02-12 09:11:27 -0500355 public void setUserImportance(int importance) {
356 mUserImportance = importance;
357 applyUserImportance();
Chris Wrenbdf33762015-12-04 15:50:51 -0500358 }
359
Julia Reynoldsef37f282016-02-12 09:11:27 -0500360 private String getUserExplanation() {
361 if (mUserExplanation == null) {
362 mUserExplanation =
363 mContext.getString(com.android.internal.R.string.importance_from_user);
Chris Wrenbdf33762015-12-04 15:50:51 -0500364 }
Julia Reynoldsef37f282016-02-12 09:11:27 -0500365 return mUserExplanation;
Chris Wrenbdf33762015-12-04 15:50:51 -0500366 }
367
368 private String getPeopleExplanation() {
369 if (mPeopleExplanation == null) {
370 mPeopleExplanation =
371 mContext.getString(com.android.internal.R.string.importance_from_person);
372 }
373 return mPeopleExplanation;
374 }
375
Julia Reynoldsef37f282016-02-12 09:11:27 -0500376 private void applyUserImportance() {
377 if (mUserImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
378 mImportance = mUserImportance;
379 mImportanceExplanation = getUserExplanation();
Julia Reynolds5d25ee72015-11-20 15:38:20 -0500380 }
381 }
382
Julia Reynoldsef37f282016-02-12 09:11:27 -0500383 public int getUserImportance() {
384 return mUserImportance;
Julia Reynolds5d25ee72015-11-20 15:38:20 -0500385 }
386
Chris Wrenbdf33762015-12-04 15:50:51 -0500387 public void setImportance(int importance, CharSequence explanation) {
388 if (importance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
389 mImportance = importance;
390 mImportanceExplanation = explanation;
391 }
Julia Reynoldsef37f282016-02-12 09:11:27 -0500392 applyUserImportance();
Chris Wrenbdf33762015-12-04 15:50:51 -0500393 }
394
395 public int getImportance() {
396 return mImportance;
397 }
398
399 public CharSequence getImportanceExplanation() {
400 return mImportanceExplanation;
401 }
402
Chris Wren333a61c2014-05-28 16:40:57 -0400403 public boolean setIntercepted(boolean intercept) {
404 mIntercept = intercept;
405 return mIntercept;
406 }
407
408 public boolean isIntercepted() {
409 return mIntercept;
410 }
411
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500412 public void setSuppressedVisualEffects(int effects) {
413 mSuppressedVisualEffects = effects;
414 }
415
416 public int getSuppressedVisualEffects() {
417 return mSuppressedVisualEffects;
418 }
419
John Spurlock312d1d02014-07-08 10:24:57 -0400420 public boolean isCategory(String category) {
John Spurlockbfa5dc42014-07-28 23:30:45 -0400421 return Objects.equals(getNotification().category, category);
422 }
423
424 public boolean isAudioStream(int stream) {
425 return getNotification().audioStreamType == stream;
426 }
427
428 public boolean isAudioAttributesUsage(int usage) {
429 final AudioAttributes attributes = getNotification().audioAttributes;
430 return attributes != null && attributes.getUsage() == usage;
John Spurlock312d1d02014-07-08 10:24:57 -0400431 }
432
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200433 /**
434 * Returns the timestamp to use for time-based sorting in the ranker.
435 */
436 public long getRankingTimeMs() {
437 return mRankingTimeMs;
438 }
439
440 /**
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400441 * @param now this current time in milliseconds.
442 * @returns the number of milliseconds since the most recent update, or the post time if none.
Chris Wren6650e572015-05-15 17:19:25 -0400443 */
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400444 public int getFreshnessMs(long now) {
445 return (int) (now - mUpdateTimeMs);
Chris Wren6650e572015-05-15 17:19:25 -0400446 }
447
448 /**
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400449 * @param now this current time in milliseconds.
450 * @returns the number of milliseconds since the the first post, ignoring updates.
Chris Wren640e3872015-04-21 13:23:18 -0400451 */
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400452 public int getLifespanMs(long now) {
453 return (int) (now - mCreationTimeMs);
Chris Wren640e3872015-04-21 13:23:18 -0400454 }
455
456 /**
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400457 * @param now this current time in milliseconds.
458 * @returns the number of milliseconds since the most recent visibility event, or 0 if never.
Chris Wren6650e572015-05-15 17:19:25 -0400459 */
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400460 public int getExposureMs(long now) {
461 return mVisibleSinceMs == 0 ? 0 : (int) (now - mVisibleSinceMs);
Chris Wren6650e572015-05-15 17:19:25 -0400462 }
463
464 /**
465 * Set the visibility of the notification.
466 */
Chris Wrend1dbc922015-06-19 17:51:16 -0400467 public void setVisibility(boolean visible, int rank) {
Chris Wren6650e572015-05-15 17:19:25 -0400468 final long now = System.currentTimeMillis();
Chris Wrene6ddb8a2015-05-27 15:21:00 -0400469 mVisibleSinceMs = visible ? now : mVisibleSinceMs;
Chris Wren6650e572015-05-15 17:19:25 -0400470 stats.onVisibilityChanged(visible);
471 EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
472 (int) (now - mCreationTimeMs),
Chris Wrend1dbc922015-06-19 17:51:16 -0400473 (int) (now - mUpdateTimeMs),
474 0, // exposure time
475 rank);
Chris Wren6650e572015-05-15 17:19:25 -0400476 }
477
478 /**
Christoph Studer52b7a5a2014-06-06 16:09:15 +0200479 * @param previousRankingTimeMs for updated notifications, {@link #getRankingTimeMs()}
480 * of the previous notification record, 0 otherwise
481 */
482 private long calculateRankingTimeMs(long previousRankingTimeMs) {
483 Notification n = getNotification();
484 // Take developer provided 'when', unless it's in the future.
485 if (n.when != 0 && n.when <= sbn.getPostTime()) {
486 return n.when;
487 }
488 // If we've ranked a previous instance with a timestamp, inherit it. This case is
489 // important in order to have ranking stability for updating notifications.
490 if (previousRankingTimeMs > 0) {
491 return previousRankingTimeMs;
492 }
493 return sbn.getPostTime();
494 }
Chris Wren1031c972014-07-23 13:11:45 +0000495
Christoph Studercd4adf82014-08-19 17:50:49 +0200496 public void setGlobalSortKey(String globalSortKey) {
497 mGlobalSortKey = globalSortKey;
Chris Wren1031c972014-07-23 13:11:45 +0000498 }
499
Christoph Studercd4adf82014-08-19 17:50:49 +0200500 public String getGlobalSortKey() {
501 return mGlobalSortKey;
Chris Wren1031c972014-07-23 13:11:45 +0000502 }
503
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700504 /** Check if any of the listeners have marked this notification as seen by the user. */
505 public boolean isSeen() {
506 return mIsSeen;
507 }
508
509 /** Mark the notification as seen by the user. */
510 public void setSeen() {
511 mIsSeen = true;
512 }
513
Chris Wren1031c972014-07-23 13:11:45 +0000514 public void setAuthoritativeRank(int authoritativeRank) {
515 mAuthoritativeRank = authoritativeRank;
516 }
517
518 public int getAuthoritativeRank() {
519 return mAuthoritativeRank;
520 }
521
522 public String getGroupKey() {
523 return sbn.getGroupKey();
524 }
Chris Wren47633422016-01-22 09:56:59 -0500525
526 public boolean isImportanceFromUser() {
Julia Reynoldsef37f282016-02-12 09:11:27 -0500527 return mImportance == mUserImportance;
Chris Wren47633422016-01-22 09:56:59 -0500528 }
Chris Wren333a61c2014-05-28 16:40:57 -0400529}