1333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren/*
2333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * Copyright (C) 2014 The Android Open Source Project
3333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *
4333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * Licensed under the Apache License, Version 2.0 (the "License");
5333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * you may not use this file except in compliance with the License.
6333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * You may obtain a copy of the License at
7333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *
8333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *      http://www.apache.org/licenses/LICENSE-2.0
9333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *
10333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * Unless required by applicable law or agreed to in writing, software
11333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * distributed under the License is distributed on an "AS IS" BASIS,
12333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * See the License for the specific language governing permissions and
14333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * limitations under the License.
15333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren */
16333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenpackage com.android.server.notification;
17333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
18333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport android.app.Notification;
19333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport android.content.Context;
20333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport android.content.pm.PackageManager.NameNotFoundException;
21333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport android.content.res.Resources;
22333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport android.graphics.Bitmap;
23d63f9321e62064660d426efd5abbd885c4a24652Dan Sandlerimport android.graphics.drawable.Icon;
24bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlockimport android.media.AudioAttributes;
25da4bd209cffad7e47a4bc6e9f02c4bfc333d3d8dChris Wrenimport android.os.UserHandle;
26333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport android.service.notification.StatusBarNotification;
27bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock
281031c974855ff4117a6d7866e664295786840319Chris Wrenimport com.android.internal.annotations.VisibleForTesting;
296650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wrenimport com.android.server.EventLogTags;
30333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
31333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport java.io.PrintWriter;
32333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport java.lang.reflect.Array;
33333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenimport java.util.Arrays;
34312d1d01def474e39e4dabbf4aef0b8adaa7caedJohn Spurlockimport java.util.Objects;
35333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
36333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren/**
37333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * Holds data about notifications that should not be shared with the
38333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * {@link android.service.notification.NotificationListenerService}s.
39333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *
40333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * <p>These objects should not be mutated unless the code is synchronized
41333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * on {@link NotificationManagerService#mNotificationList}, and any
42333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * modification should be followed by a sorting of that list.</p>
43333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *
44333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * <p>Is sortable by {@link NotificationComparator}.</p>
45333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren *
46333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren * {@hide}
47333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren */
48333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wrenpublic final class NotificationRecord {
49333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    final StatusBarNotification sbn;
50365e4c38d58d38bb61d1fdd870346f2f594825fdChristoph Studer    final int mOriginalFlags;
51365e4c38d58d38bb61d1fdd870346f2f594825fdChristoph Studer
52333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    NotificationUsageStats.SingleNotificationStats stats;
53333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    boolean isCanceled;
54a344656a010dc3c88aef39109f1ac459792e7607Chris Wren    int score;
55f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    /** Whether the notification was seen by the user via one of the notification listeners. */
56f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    boolean mIsSeen;
57333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
58333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    // These members are used by NotificationSignalExtractors
59333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    // to communicate with the ranking module.
60333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    private float mContactAffinity;
61333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    private boolean mRecentlyIntrusive;
62333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
63333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    // is this notification currently being intercepted by Zen Mode?
64333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    private boolean mIntercept;
65333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
6652b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    // The timestamp used for ranking.
6752b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    private long mRankingTimeMs;
6852b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer
69640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren    // The first post time, stable across updates.
70640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren    private long mCreationTimeMs;
71640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren
726650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    // The most recent visibility event.
736650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    private long mVisibleSinceMs;
746650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren
756650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    // The most recent update time, or the creation time if no updates.
766650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    private long mUpdateTimeMs;
776650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren
78a344656a010dc3c88aef39109f1ac459792e7607Chris Wren    // Is this record an update of an old record?
79a344656a010dc3c88aef39109f1ac459792e7607Chris Wren    public boolean isUpdate;
8054bbef435ed857fc68941672799fc8001c101119Chris Wren    private int mPackagePriority;
81a344656a010dc3c88aef39109f1ac459792e7607Chris Wren
821031c974855ff4117a6d7866e664295786840319Chris Wren    private int mAuthoritativeRank;
83cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer    private String mGlobalSortKey;
843ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren    private int mPackageVisibility;
851031c974855ff4117a6d7866e664295786840319Chris Wren
861031c974855ff4117a6d7866e664295786840319Chris Wren    @VisibleForTesting
871031c974855ff4117a6d7866e664295786840319Chris Wren    public NotificationRecord(StatusBarNotification sbn, int score)
88333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    {
89333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        this.sbn = sbn;
90a344656a010dc3c88aef39109f1ac459792e7607Chris Wren        this.score = score;
91365e4c38d58d38bb61d1fdd870346f2f594825fdChristoph Studer        mOriginalFlags = sbn.getNotification().flags;
9252b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        mRankingTimeMs = calculateRankingTimeMs(0L);
93640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren        mCreationTimeMs = sbn.getPostTime();
946650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        mUpdateTimeMs = mCreationTimeMs;
95333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
96333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
97333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    // copy any notes that the ranking system may have made before the update
98333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public void copyRankingInformation(NotificationRecord previous) {
99333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        mContactAffinity = previous.mContactAffinity;
100333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        mRecentlyIntrusive = previous.mRecentlyIntrusive;
10154bbef435ed857fc68941672799fc8001c101119Chris Wren        mPackagePriority = previous.mPackagePriority;
1023ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren        mPackageVisibility = previous.mPackageVisibility;
103333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        mIntercept = previous.mIntercept;
10452b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
105640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren        mCreationTimeMs = previous.mCreationTimeMs;
1066650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        mVisibleSinceMs = previous.mVisibleSinceMs;
107cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer        // Don't copy mGlobalSortKey, recompute it.
108333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
109333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
110333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public Notification getNotification() { return sbn.getNotification(); }
111333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public int getFlags() { return sbn.getNotification().flags; }
112da4bd209cffad7e47a4bc6e9f02c4bfc333d3d8dChris Wren    public UserHandle getUser() { return sbn.getUser(); }
113333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public String getKey() { return sbn.getKey(); }
114da4bd209cffad7e47a4bc6e9f02c4bfc333d3d8dChris Wren    /** @deprecated Use {@link #getUser()} instead. */
115da4bd209cffad7e47a4bc6e9f02c4bfc333d3d8dChris Wren    public int getUserId() { return sbn.getUserId(); }
116333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
117a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler    void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
118333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        final Notification notification = sbn.getNotification();
119d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler        final Icon icon = notification.getSmallIcon();
120d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler        String iconStr = String.valueOf(icon);
121d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler        if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
122d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler            iconStr += " / " + idDebugString(baseContext, icon.getResPackage(), icon.getResId());
123d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler        }
124333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + this);
125333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
126d63f9321e62064660d426efd5abbd885c4a24652Dan Sandler        pw.println(prefix + "  icon=" + iconStr);
127333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  pri=" + notification.priority + " score=" + sbn.getScore());
128333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  key=" + sbn.getKey());
12924bd0be558838db4ff975e97fa986eb317773fc5Amith Yamasani        pw.println(prefix + "  seen=" + mIsSeen);
1301031c974855ff4117a6d7866e664295786840319Chris Wren        pw.println(prefix + "  groupKey=" + getGroupKey());
131333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  contentIntent=" + notification.contentIntent);
132333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  deleteIntent=" + notification.deleteIntent);
133333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  tickerText=" + notification.tickerText);
134333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  contentView=" + notification.contentView);
135333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + String.format("  defaults=0x%08x flags=0x%08x",
136333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                notification.defaults, notification.flags));
137333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  sound=" + notification.sound);
138bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock        pw.println(prefix + "  audioStreamType=" + notification.audioStreamType);
139bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock        pw.println(prefix + "  audioAttributes=" + notification.audioAttributes);
140333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + String.format("  color=0x%08x", notification.color));
141333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  vibrate=" + Arrays.toString(notification.vibrate));
142333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + String.format("  led=0x%08x onMs=%d offMs=%d",
143333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                notification.ledARGB, notification.ledOnMS, notification.ledOffMS));
144333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        if (notification.actions != null && notification.actions.length > 0) {
145333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            pw.println(prefix + "  actions={");
146333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            final int N = notification.actions.length;
147333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            for (int i=0; i<N; i++) {
148333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                final Notification.Action action = notification.actions[i];
149333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                pw.println(String.format("%s    [%d] \"%s\" -> %s",
150333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        prefix,
151333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        i,
152333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        action.title,
153333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        action.actionIntent.toString()
154333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        ));
155333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            }
156333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            pw.println(prefix + "  }");
157333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        }
158333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        if (notification.extras != null && notification.extras.size() > 0) {
159333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            pw.println(prefix + "  extras={");
160333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            for (String key : notification.extras.keySet()) {
161333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                pw.print(prefix + "    " + key + "=");
162333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                Object val = notification.extras.get(key);
163333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                if (val == null) {
164333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    pw.println("null");
165333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                } else {
166333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    pw.print(val.getClass().getSimpleName());
167a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                    if (redact && (val instanceof CharSequence || val instanceof String)) {
168333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        // redact contents from bugreports
169333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    } else if (val instanceof Bitmap) {
170333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        pw.print(String.format(" (%dx%d)",
171333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                                ((Bitmap) val).getWidth(),
172333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                                ((Bitmap) val).getHeight()));
173333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    } else if (val.getClass().isArray()) {
174333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        final int N = Array.getLength(val);
175a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                        pw.print(" (" + N + ")");
176a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                        if (!redact) {
177a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                            for (int j=0; j<N; j++) {
178a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                                pw.println();
179a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                                pw.print(String.format("%s      [%d] %s",
180a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                                        prefix, j, String.valueOf(Array.get(val, j))));
181a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                            }
182a17703138b0c51226c0e73dd8d34ea037d260aebDan Sandler                        }
183333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    } else {
184333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                        pw.print(" (" + String.valueOf(val) + ")");
185333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    }
186333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                    pw.println();
187333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                }
188333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            }
189333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            pw.println(prefix + "  }");
190333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        }
191333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  stats=" + stats.toString());
192333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  mContactAffinity=" + mContactAffinity);
193333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  mRecentlyIntrusive=" + mRecentlyIntrusive);
19454bbef435ed857fc68941672799fc8001c101119Chris Wren        pw.println(prefix + "  mPackagePriority=" + mPackagePriority);
1953ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren        pw.println(prefix + "  mPackageVisibility=" + mPackageVisibility);
196333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        pw.println(prefix + "  mIntercept=" + mIntercept);
197cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer        pw.println(prefix + "  mGlobalSortKey=" + mGlobalSortKey);
19852b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        pw.println(prefix + "  mRankingTimeMs=" + mRankingTimeMs);
199640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren        pw.println(prefix + "  mCreationTimeMs=" + mCreationTimeMs);
2006650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        pw.println(prefix + "  mVisibleSinceMs=" + mVisibleSinceMs);
2016650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        pw.println(prefix + "  mUpdateTimeMs=" + mUpdateTimeMs);
202333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
203333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
204333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
205333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    static String idDebugString(Context baseContext, String packageName, int id) {
206333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        Context c;
207333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
208333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        if (packageName != null) {
209333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            try {
210333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                c = baseContext.createPackageContext(packageName, 0);
211333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            } catch (NameNotFoundException e) {
212333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                c = baseContext;
213333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            }
214333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        } else {
215333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            c = baseContext;
216333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        }
217333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
218333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        Resources r = c.getResources();
219333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        try {
220333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            return r.getResourceName(id);
221333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        } catch (Resources.NotFoundException e) {
222333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren            return "<name unknown>";
223333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        }
224333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
225333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
226333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    @Override
227333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public final String toString() {
228333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        return String.format(
229333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
230333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                System.identityHashCode(this),
231333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
232333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(),
233333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren                this.sbn.getNotification());
234333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
235333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
236333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public void setContactAffinity(float contactAffinity) {
237333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        mContactAffinity = contactAffinity;
238333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
239333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
240333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public float getContactAffinity() {
241333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        return mContactAffinity;
242333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
243333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
2441d881a1e986c706963c254fbe2b6296a1cd10b75John Spurlock    public void setRecentlyIntrusive(boolean recentlyIntrusive) {
245333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        mRecentlyIntrusive = recentlyIntrusive;
246333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
247333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
248333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public boolean isRecentlyIntrusive() {
249333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        return mRecentlyIntrusive;
250333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
251333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
25254bbef435ed857fc68941672799fc8001c101119Chris Wren    public void setPackagePriority(int packagePriority) {
2536ac5f8df62a4b6d87cf32797d2886efab8e28226John Spurlock        mPackagePriority = packagePriority;
25454bbef435ed857fc68941672799fc8001c101119Chris Wren    }
25554bbef435ed857fc68941672799fc8001c101119Chris Wren
25654bbef435ed857fc68941672799fc8001c101119Chris Wren    public int getPackagePriority() {
25754bbef435ed857fc68941672799fc8001c101119Chris Wren        return mPackagePriority;
25854bbef435ed857fc68941672799fc8001c101119Chris Wren    }
25954bbef435ed857fc68941672799fc8001c101119Chris Wren
2603ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren    public void setPackageVisibilityOverride(int packageVisibility) {
2613ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren        mPackageVisibility = packageVisibility;
2623ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren    }
2633ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren
2643ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren    public int getPackageVisibilityOverride() {
2653ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren        return mPackageVisibility;
2663ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren    }
2673ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren
268333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public boolean setIntercepted(boolean intercept) {
269333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        mIntercept = intercept;
270333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        return mIntercept;
271333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
272333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
273333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    public boolean isIntercepted() {
274333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren        return mIntercept;
275333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren    }
276333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren
277312d1d01def474e39e4dabbf4aef0b8adaa7caedJohn Spurlock    public boolean isCategory(String category) {
278bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock        return Objects.equals(getNotification().category, category);
279bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock    }
280bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock
281bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock    public boolean isAudioStream(int stream) {
282bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock        return getNotification().audioStreamType == stream;
283bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock    }
284bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock
285bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock    public boolean isAudioAttributesUsage(int usage) {
286bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock        final AudioAttributes attributes = getNotification().audioAttributes;
287bfa5dc4c6c486bdabadb5ea2e356a7d348e3b975John Spurlock        return attributes != null && attributes.getUsage() == usage;
288312d1d01def474e39e4dabbf4aef0b8adaa7caedJohn Spurlock    }
289312d1d01def474e39e4dabbf4aef0b8adaa7caedJohn Spurlock
29052b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    /**
29152b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer     * Returns the timestamp to use for time-based sorting in the ranker.
29252b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer     */
29352b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    public long getRankingTimeMs() {
29452b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        return mRankingTimeMs;
29552b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    }
29652b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer
29752b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    /**
298e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren     * @param now this current time in milliseconds.
299e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren     * @returns the number of milliseconds since the most recent update, or the post time if none.
3006650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren     */
301e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren    public int getFreshnessMs(long now) {
302e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren        return (int) (now - mUpdateTimeMs);
3036650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    }
3046650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren
3056650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    /**
306e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren     * @param now this current time in milliseconds.
307e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren     * @returns the number of milliseconds since the the first post, ignoring updates.
308640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren     */
309e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren    public int getLifespanMs(long now) {
310e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren        return (int) (now - mCreationTimeMs);
311640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren    }
312640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren
313640e387ce4e8aa97a8139fda54a5f5468e2ff18bChris Wren    /**
314e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren     * @param now this current time in milliseconds.
315e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren     * @returns the number of milliseconds since the most recent visibility event, or 0 if never.
3166650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren     */
317e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren    public int getExposureMs(long now) {
318e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren        return mVisibleSinceMs == 0 ? 0 : (int) (now - mVisibleSinceMs);
3196650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    }
3206650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren
3216650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    /**
3226650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren     * Set the visibility of the notification.
3236650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren     */
324d1dbc92d67af4cb72bb2faff9011d36b6833bbfdChris Wren    public void setVisibility(boolean visible, int rank) {
3256650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        final long now = System.currentTimeMillis();
326e6ddb8a1348d2ea53bc3033be43c4dae922b653aChris Wren        mVisibleSinceMs = visible ? now : mVisibleSinceMs;
3276650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        stats.onVisibilityChanged(visible);
3286650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren        EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
3296650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren                (int) (now - mCreationTimeMs),
330d1dbc92d67af4cb72bb2faff9011d36b6833bbfdChris Wren                (int) (now - mUpdateTimeMs),
331d1dbc92d67af4cb72bb2faff9011d36b6833bbfdChris Wren                0, // exposure time
332d1dbc92d67af4cb72bb2faff9011d36b6833bbfdChris Wren                rank);
3336650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    }
3346650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren
3356650e5767b3d69268af7238cfa65dde6a9f2e0a3Chris Wren    /**
33652b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer     * @param previousRankingTimeMs for updated notifications, {@link #getRankingTimeMs()}
33752b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer     *     of the previous notification record, 0 otherwise
33852b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer     */
33952b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    private long calculateRankingTimeMs(long previousRankingTimeMs) {
34052b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        Notification n = getNotification();
34152b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        // Take developer provided 'when', unless it's in the future.
34252b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        if (n.when != 0 && n.when <= sbn.getPostTime()) {
34352b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer            return n.when;
34452b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        }
34552b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        // If we've ranked a previous instance with a timestamp, inherit it. This case is
34652b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        // important in order to have ranking stability for updating notifications.
34752b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        if (previousRankingTimeMs > 0) {
34852b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer            return previousRankingTimeMs;
34952b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        }
35052b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer        return sbn.getPostTime();
35152b7a5a5973c05fe59b751b82ee357fdfc1c5ef7Christoph Studer    }
3521031c974855ff4117a6d7866e664295786840319Chris Wren
353cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer    public void setGlobalSortKey(String globalSortKey) {
354cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer        mGlobalSortKey = globalSortKey;
3551031c974855ff4117a6d7866e664295786840319Chris Wren    }
3561031c974855ff4117a6d7866e664295786840319Chris Wren
357cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer    public String getGlobalSortKey() {
358cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer        return mGlobalSortKey;
3591031c974855ff4117a6d7866e664295786840319Chris Wren    }
3601031c974855ff4117a6d7866e664295786840319Chris Wren
361f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    /** Check if any of the listeners have marked this notification as seen by the user. */
362f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    public boolean isSeen() {
363f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani        return mIsSeen;
364f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    }
365f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani
366f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    /** Mark the notification as seen by the user. */
367f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    public void setSeen() {
368f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani        mIsSeen = true;
369f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani    }
370f47e51ec605fccf7fed9e50d1adc98fbd4e8b340Amith Yamasani
3711031c974855ff4117a6d7866e664295786840319Chris Wren    public void setAuthoritativeRank(int authoritativeRank) {
3721031c974855ff4117a6d7866e664295786840319Chris Wren        mAuthoritativeRank = authoritativeRank;
3731031c974855ff4117a6d7866e664295786840319Chris Wren    }
3741031c974855ff4117a6d7866e664295786840319Chris Wren
3751031c974855ff4117a6d7866e664295786840319Chris Wren    public int getAuthoritativeRank() {
3761031c974855ff4117a6d7866e664295786840319Chris Wren        return mAuthoritativeRank;
3771031c974855ff4117a6d7866e664295786840319Chris Wren    }
3781031c974855ff4117a6d7866e664295786840319Chris Wren
3791031c974855ff4117a6d7866e664295786840319Chris Wren    public String getGroupKey() {
3801031c974855ff4117a6d7866e664295786840319Chris Wren        return sbn.getGroupKey();
3811031c974855ff4117a6d7866e664295786840319Chris Wren    }
382333a61c3a5a83fe9c50ebeb5c947317f61385b7bChris Wren}
383