Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 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 | */ |
| 16 | |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 17 | package android.service.notification; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 18 | |
Julia Reynolds | 7c26752 | 2020-01-16 11:26:41 -0500 | [diff] [blame] | 19 | import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID; |
Julia Reynolds | 7c26752 | 2020-01-16 11:26:41 -0500 | [diff] [blame] | 20 | |
Julia Reynolds | cbc45e7 | 2019-03-07 12:31:52 -0500 | [diff] [blame] | 21 | import android.annotation.NonNull; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 22 | import android.app.Notification; |
Julia Reynolds | a7ba45a | 2018-08-29 09:07:52 -0400 | [diff] [blame] | 23 | import android.app.NotificationManager; |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 24 | import android.app.Person; |
Artur Satayev | df43959 | 2019-12-10 17:47:53 +0000 | [diff] [blame] | 25 | import android.compat.annotation.UnsupportedAppUsage; |
Dan Sandler | 68079d5 | 2015-07-22 10:45:30 -0400 | [diff] [blame] | 26 | import android.content.Context; |
| 27 | import android.content.pm.ApplicationInfo; |
| 28 | import android.content.pm.PackageManager; |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 29 | import android.metrics.LogMaker; |
Mathew Inwood | 31755f9 | 2018-12-20 13:53:36 +0000 | [diff] [blame] | 30 | import android.os.Build; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 31 | import android.os.Parcel; |
| 32 | import android.os.Parcelable; |
Dianne Hackborn | f02b60a | 2012-08-16 10:48:27 -0700 | [diff] [blame] | 33 | import android.os.UserHandle; |
Julia Reynolds | e24faa2 | 2020-04-02 12:44:47 -0400 | [diff] [blame] | 34 | import android.provider.Settings; |
Julia Reynolds | 7c26752 | 2020-01-16 11:26:41 -0500 | [diff] [blame] | 35 | import android.text.TextUtils; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 36 | |
Will Brockman | cfd9830 | 2020-01-29 15:57:30 -0500 | [diff] [blame] | 37 | import com.android.internal.logging.InstanceId; |
Will Brockman | 828427e | 2019-01-28 09:55:45 -0500 | [diff] [blame] | 38 | import com.android.internal.logging.nano.MetricsProto; |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 39 | import com.android.internal.logging.nano.MetricsProto.MetricsEvent; |
| 40 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 41 | import java.util.ArrayList; |
| 42 | |
Daniel Sandler | 2561b0b | 2012-02-13 21:04:12 -0500 | [diff] [blame] | 43 | /** |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 44 | * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 45 | * the status bar and any {@link android.service.notification.NotificationListenerService}s. |
Daniel Sandler | 2561b0b | 2012-02-13 21:04:12 -0500 | [diff] [blame] | 46 | */ |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 47 | public class StatusBarNotification implements Parcelable { |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 48 | static final int MAX_LOG_TAG_LENGTH = 36; |
| 49 | |
Mathew Inwood | e380737 | 2018-08-10 09:51:03 +0100 | [diff] [blame] | 50 | @UnsupportedAppUsage |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 51 | private final String pkg; |
Mathew Inwood | e380737 | 2018-08-10 09:51:03 +0100 | [diff] [blame] | 52 | @UnsupportedAppUsage |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 53 | private final int id; |
Mathew Inwood | 31755f9 | 2018-12-20 13:53:36 +0000 | [diff] [blame] | 54 | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 55 | private final String tag; |
John Spurlock | a429429 | 2014-03-24 18:02:32 -0400 | [diff] [blame] | 56 | private final String key; |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 57 | private String groupKey; |
| 58 | private String overrideGroupKey; |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 59 | |
Mathew Inwood | e380737 | 2018-08-10 09:51:03 +0100 | [diff] [blame] | 60 | @UnsupportedAppUsage |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 61 | private final int uid; |
Christoph Studer | 8fd7f1e | 2014-04-11 17:35:05 -0400 | [diff] [blame] | 62 | private final String opPkg; |
Mathew Inwood | 31755f9 | 2018-12-20 13:53:36 +0000 | [diff] [blame] | 63 | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 64 | private final int initialPid; |
Mathew Inwood | 31755f9 | 2018-12-20 13:53:36 +0000 | [diff] [blame] | 65 | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 66 | private final Notification notification; |
Mathew Inwood | 31755f9 | 2018-12-20 13:53:36 +0000 | [diff] [blame] | 67 | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 68 | private final UserHandle user; |
Mathew Inwood | 31755f9 | 2018-12-20 13:53:36 +0000 | [diff] [blame] | 69 | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 70 | private final long postTime; |
Will Brockman | cfd9830 | 2020-01-29 15:57:30 -0500 | [diff] [blame] | 71 | // A small per-notification ID, used for statsd logging. |
| 72 | private InstanceId mInstanceId; // Not final, see setInstanceId() |
Jeff Sharkey | 6d51571 | 2012-09-20 16:06:08 -0700 | [diff] [blame] | 73 | |
Dan Sandler | 68079d5 | 2015-07-22 10:45:30 -0400 | [diff] [blame] | 74 | private Context mContext; // used for inflation & icon expansion |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 75 | |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 76 | /** @hide */ |
Julia Reynolds | 924eed1 | 2017-01-19 09:52:07 -0500 | [diff] [blame] | 77 | public StatusBarNotification(String pkg, String opPkg, int id, |
Julia Reynolds | 423b9fc | 2016-11-09 09:51:08 -0500 | [diff] [blame] | 78 | String tag, int uid, int initialPid, Notification notification, UserHandle user, |
| 79 | String overrideGroupKey, long postTime) { |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 80 | if (pkg == null) throw new NullPointerException(); |
| 81 | if (notification == null) throw new NullPointerException(); |
| 82 | |
| 83 | this.pkg = pkg; |
| 84 | this.opPkg = opPkg; |
| 85 | this.id = id; |
| 86 | this.tag = tag; |
| 87 | this.uid = uid; |
| 88 | this.initialPid = initialPid; |
| 89 | this.notification = notification; |
| 90 | this.user = user; |
| 91 | this.postTime = postTime; |
| 92 | this.overrideGroupKey = overrideGroupKey; |
| 93 | this.key = key(); |
| 94 | this.groupKey = groupKey(); |
| 95 | } |
| 96 | |
Julia Reynolds | a11d0b1 | 2017-02-16 15:01:36 -0500 | [diff] [blame] | 97 | /** |
| 98 | * @deprecated Non-system apps should not need to create StatusBarNotifications. |
| 99 | */ |
Julia Reynolds | 423b9fc | 2016-11-09 09:51:08 -0500 | [diff] [blame] | 100 | @Deprecated |
Christoph Studer | 8fd7f1e | 2014-04-11 17:35:05 -0400 | [diff] [blame] | 101 | public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 102 | int initialPid, int score, Notification notification, UserHandle user, |
| 103 | long postTime) { |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 104 | if (pkg == null) throw new NullPointerException(); |
| 105 | if (notification == null) throw new NullPointerException(); |
| 106 | |
| 107 | this.pkg = pkg; |
Christoph Studer | 8fd7f1e | 2014-04-11 17:35:05 -0400 | [diff] [blame] | 108 | this.opPkg = opPkg; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 109 | this.id = id; |
| 110 | this.tag = tag; |
Dianne Hackborn | 9d39d0c | 2010-06-24 15:57:42 -0700 | [diff] [blame] | 111 | this.uid = uid; |
| 112 | this.initialPid = initialPid; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 113 | this.notification = notification; |
Jeff Sharkey | 6d51571 | 2012-09-20 16:06:08 -0700 | [diff] [blame] | 114 | this.user = user; |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 115 | this.postTime = postTime; |
John Spurlock | a429429 | 2014-03-24 18:02:32 -0400 | [diff] [blame] | 116 | this.key = key(); |
Chris Wren | 1031c97 | 2014-07-23 13:11:45 +0000 | [diff] [blame] | 117 | this.groupKey = groupKey(); |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | public StatusBarNotification(Parcel in) { |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 121 | this.pkg = in.readString(); |
Christoph Studer | 8fd7f1e | 2014-04-11 17:35:05 -0400 | [diff] [blame] | 122 | this.opPkg = in.readString(); |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 123 | this.id = in.readInt(); |
| 124 | if (in.readInt() != 0) { |
| 125 | this.tag = in.readString(); |
| 126 | } else { |
| 127 | this.tag = null; |
| 128 | } |
Dianne Hackborn | 9d39d0c | 2010-06-24 15:57:42 -0700 | [diff] [blame] | 129 | this.uid = in.readInt(); |
| 130 | this.initialPid = in.readInt(); |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 131 | this.notification = new Notification(in); |
Jeff Sharkey | 6d51571 | 2012-09-20 16:06:08 -0700 | [diff] [blame] | 132 | this.user = UserHandle.readFromParcel(in); |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 133 | this.postTime = in.readLong(); |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 134 | if (in.readInt() != 0) { |
| 135 | this.overrideGroupKey = in.readString(); |
Will Brockman | cfd9830 | 2020-01-29 15:57:30 -0500 | [diff] [blame] | 136 | } |
| 137 | if (in.readInt() != 0) { |
| 138 | this.mInstanceId = InstanceId.CREATOR.createFromParcel(in); |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 139 | } |
John Spurlock | a429429 | 2014-03-24 18:02:32 -0400 | [diff] [blame] | 140 | this.key = key(); |
Chris Wren | 1031c97 | 2014-07-23 13:11:45 +0000 | [diff] [blame] | 141 | this.groupKey = groupKey(); |
John Spurlock | a429429 | 2014-03-24 18:02:32 -0400 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | private String key() { |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 145 | String sbnKey = user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid; |
| 146 | if (overrideGroupKey != null && getNotification().isGroupSummary()) { |
| 147 | sbnKey = sbnKey + "|" + overrideGroupKey; |
| 148 | } |
| 149 | return sbnKey; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 150 | } |
| 151 | |
Chris Wren | 1031c97 | 2014-07-23 13:11:45 +0000 | [diff] [blame] | 152 | private String groupKey() { |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 153 | if (overrideGroupKey != null) { |
| 154 | return user.getIdentifier() + "|" + pkg + "|" + "g:" + overrideGroupKey; |
| 155 | } |
Chris Wren | 1031c97 | 2014-07-23 13:11:45 +0000 | [diff] [blame] | 156 | final String group = getNotification().getGroup(); |
| 157 | final String sortKey = getNotification().getSortKey(); |
| 158 | if (group == null && sortKey == null) { |
| 159 | // a group of one |
| 160 | return key; |
| 161 | } |
| 162 | return user.getIdentifier() + "|" + pkg + "|" + |
| 163 | (group == null |
Julia Reynolds | bad4297 | 2017-04-25 13:52:49 -0400 | [diff] [blame] | 164 | ? "c:" + notification.getChannelId() |
Chris Wren | 1031c97 | 2014-07-23 13:11:45 +0000 | [diff] [blame] | 165 | : "g:" + group); |
| 166 | } |
| 167 | |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 168 | /** |
| 169 | * Returns true if this notification is part of a group. |
| 170 | */ |
| 171 | public boolean isGroup() { |
Chris Wren | 8a1638f | 2016-05-02 16:19:14 -0400 | [diff] [blame] | 172 | if (overrideGroupKey != null || isAppGroup()) { |
| 173 | return true; |
| 174 | } |
| 175 | return false; |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Returns true if application asked that this notification be part of a group. |
Chris Wren | 8a1638f | 2016-05-02 16:19:14 -0400 | [diff] [blame] | 180 | */ |
| 181 | public boolean isAppGroup() { |
| 182 | if (getNotification().getGroup() != null || getNotification().getSortKey() != null) { |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 183 | return true; |
| 184 | } |
| 185 | return false; |
| 186 | } |
| 187 | |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 188 | public void writeToParcel(Parcel out, int flags) { |
| 189 | out.writeString(this.pkg); |
Christoph Studer | 8fd7f1e | 2014-04-11 17:35:05 -0400 | [diff] [blame] | 190 | out.writeString(this.opPkg); |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 191 | out.writeInt(this.id); |
| 192 | if (this.tag != null) { |
| 193 | out.writeInt(1); |
| 194 | out.writeString(this.tag); |
| 195 | } else { |
| 196 | out.writeInt(0); |
| 197 | } |
Dianne Hackborn | 9d39d0c | 2010-06-24 15:57:42 -0700 | [diff] [blame] | 198 | out.writeInt(this.uid); |
| 199 | out.writeInt(this.initialPid); |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 200 | this.notification.writeToParcel(out, flags); |
Jeff Sharkey | 6d51571 | 2012-09-20 16:06:08 -0700 | [diff] [blame] | 201 | user.writeToParcel(out, flags); |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 202 | out.writeLong(this.postTime); |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 203 | if (this.overrideGroupKey != null) { |
| 204 | out.writeInt(1); |
| 205 | out.writeString(this.overrideGroupKey); |
| 206 | } else { |
| 207 | out.writeInt(0); |
| 208 | } |
Will Brockman | cfd9830 | 2020-01-29 15:57:30 -0500 | [diff] [blame] | 209 | if (this.mInstanceId != null) { |
| 210 | out.writeInt(1); |
| 211 | mInstanceId.writeToParcel(out, flags); |
| 212 | } else { |
| 213 | out.writeInt(0); |
| 214 | } |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | public int describeContents() { |
| 218 | return 0; |
| 219 | } |
| 220 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 221 | public static final @android.annotation.NonNull |
| 222 | Parcelable.Creator<StatusBarNotification> CREATOR = |
| 223 | new Parcelable.Creator<StatusBarNotification>() { |
| 224 | public StatusBarNotification createFromParcel(Parcel parcel) { |
| 225 | return new StatusBarNotification(parcel); |
| 226 | } |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 227 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 228 | public StatusBarNotification[] newArray(int size) { |
| 229 | return new StatusBarNotification[size]; |
| 230 | } |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 231 | }; |
| 232 | |
Daniel Sandler | 1a497d3 | 2013-04-18 14:52:45 -0400 | [diff] [blame] | 233 | /** |
| 234 | * @hide |
| 235 | */ |
| 236 | public StatusBarNotification cloneLight() { |
| 237 | final Notification no = new Notification(); |
| 238 | this.notification.cloneInto(no, false); // light copy |
Will Brockman | 492b381 | 2020-03-03 16:29:36 +0000 | [diff] [blame] | 239 | return cloneShallow(no); |
Daniel Sandler | 1a497d3 | 2013-04-18 14:52:45 -0400 | [diff] [blame] | 240 | } |
| 241 | |
Jeff Sharkey | 6d51571 | 2012-09-20 16:06:08 -0700 | [diff] [blame] | 242 | @Override |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 243 | public StatusBarNotification clone() { |
Will Brockman | 492b381 | 2020-03-03 16:29:36 +0000 | [diff] [blame] | 244 | return cloneShallow(this.notification.clone()); |
| 245 | } |
| 246 | |
| 247 | /** |
| 248 | * @param notification Some kind of clone of this.notification. |
| 249 | * @return A shallow copy of self, with notification in place of this.notification. |
| 250 | */ |
| 251 | StatusBarNotification cloneShallow(Notification notification) { |
| 252 | StatusBarNotification result = new StatusBarNotification(this.pkg, this.opPkg, |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 253 | this.id, this.tag, this.uid, this.initialPid, |
Will Brockman | 492b381 | 2020-03-03 16:29:36 +0000 | [diff] [blame] | 254 | notification, this.user, this.overrideGroupKey, this.postTime); |
| 255 | result.setInstanceId(this.mInstanceId); |
| 256 | return result; |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 257 | } |
| 258 | |
Jeff Sharkey | 6d51571 | 2012-09-20 16:06:08 -0700 | [diff] [blame] | 259 | @Override |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 260 | public String toString() { |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 261 | return String.format( |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 262 | "StatusBarNotification(pkg=%s user=%s id=%d tag=%s key=%s: %s)", |
Daniel Sandler | fde19b1 | 2013-01-17 00:21:05 -0500 | [diff] [blame] | 263 | this.pkg, this.user, this.id, this.tag, |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 264 | this.key, this.notification); |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 265 | } |
| 266 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 267 | /** |
| 268 | * Convenience method to check the notification's flags for |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 269 | * {@link Notification#FLAG_ONGOING_EVENT}. |
| 270 | */ |
Joe Onorato | e345fff | 2010-05-23 15:18:27 -0400 | [diff] [blame] | 271 | public boolean isOngoing() { |
| 272 | return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0; |
| 273 | } |
| 274 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 275 | /** |
| 276 | * Convenience method to check the notification's flags for |
Daniel Sandler | 5feceeb | 2013-03-22 18:29:23 -0700 | [diff] [blame] | 277 | * either {@link Notification#FLAG_ONGOING_EVENT} or |
| 278 | * {@link Notification#FLAG_NO_CLEAR}. |
| 279 | */ |
Joe Onorato | 5dd1169 | 2010-09-27 15:34:04 -0700 | [diff] [blame] | 280 | public boolean isClearable() { |
| 281 | return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) |
| 282 | && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0); |
| 283 | } |
Daniel Sandler | b9301c3 | 2012-08-14 15:08:24 -0400 | [diff] [blame] | 284 | |
Kenny Guy | a263e4e | 2014-03-03 18:24:03 +0000 | [diff] [blame] | 285 | /** |
Julia Reynolds | d5261e1 | 2016-12-19 14:14:25 -0500 | [diff] [blame] | 286 | * Returns a userid for whom this notification is intended. |
Kenny Guy | a263e4e | 2014-03-03 18:24:03 +0000 | [diff] [blame] | 287 | * |
| 288 | * @deprecated Use {@link #getUser()} instead. |
| 289 | */ |
Aurimas Liutikas | 514c5ef | 2016-05-24 15:22:55 -0700 | [diff] [blame] | 290 | @Deprecated |
Daniel Sandler | b9301c3 | 2012-08-14 15:08:24 -0400 | [diff] [blame] | 291 | public int getUserId() { |
Dianne Hackborn | 50cdf7c3 | 2012-09-23 17:08:57 -0700 | [diff] [blame] | 292 | return this.user.getIdentifier(); |
Daniel Sandler | b9301c3 | 2012-08-14 15:08:24 -0400 | [diff] [blame] | 293 | } |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 294 | |
Julia Reynolds | b5535c6 | 2020-04-13 11:03:44 -0400 | [diff] [blame] | 295 | /** |
| 296 | * Like {@link #getUserId()} but handles special users. |
| 297 | * @hide |
| 298 | */ |
| 299 | public int getNormalizedUserId() { |
| 300 | int userId = getUserId(); |
| 301 | if (userId == UserHandle.USER_ALL) { |
| 302 | userId = UserHandle.USER_SYSTEM; |
| 303 | } |
| 304 | return userId; |
| 305 | } |
| 306 | |
Julia Reynolds | a7ba45a | 2018-08-29 09:07:52 -0400 | [diff] [blame] | 307 | /** The package that the notification belongs to. */ |
Daniel Sandler | 4f91efd | 2013-04-25 16:38:41 -0400 | [diff] [blame] | 308 | public String getPackageName() { |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 309 | return pkg; |
| 310 | } |
| 311 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 312 | /** The id supplied to {@link android.app.NotificationManager#notify(int, Notification)}. */ |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 313 | public int getId() { |
| 314 | return id; |
| 315 | } |
| 316 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 317 | /** |
| 318 | * The tag supplied to {@link android.app.NotificationManager#notify(int, Notification)}, |
| 319 | * or null if no tag was specified. |
| 320 | */ |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 321 | public String getTag() { |
| 322 | return tag; |
| 323 | } |
| 324 | |
Julia Reynolds | a7ba45a | 2018-08-29 09:07:52 -0400 | [diff] [blame] | 325 | /** |
| 326 | * The notifying app's ({@link #getPackageName()}'s) uid. |
| 327 | */ |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 328 | public int getUid() { |
| 329 | return uid; |
| 330 | } |
| 331 | |
Julia Reynolds | 9846076 | 2019-03-18 13:13:55 -0400 | [diff] [blame] | 332 | /** |
| 333 | * The package that posted the notification. |
| 334 | * <p> Might be different from {@link #getPackageName()} if the app owning the notification has |
Julia Reynolds | a7ba45a | 2018-08-29 09:07:52 -0400 | [diff] [blame] | 335 | * a {@link NotificationManager#setNotificationDelegate(String) notification delegate}. |
| 336 | */ |
Julia Reynolds | cbc45e7 | 2019-03-07 12:31:52 -0500 | [diff] [blame] | 337 | public @NonNull String getOpPkg() { |
Christoph Studer | 8fd7f1e | 2014-04-11 17:35:05 -0400 | [diff] [blame] | 338 | return opPkg; |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | /** @hide */ |
Mathew Inwood | e380737 | 2018-08-10 09:51:03 +0100 | [diff] [blame] | 342 | @UnsupportedAppUsage |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 343 | public int getInitialPid() { |
| 344 | return initialPid; |
| 345 | } |
| 346 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 347 | /** |
| 348 | * The {@link android.app.Notification} supplied to |
| 349 | * {@link android.app.NotificationManager#notify(int, Notification)}. |
| 350 | */ |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 351 | public Notification getNotification() { |
| 352 | return notification; |
| 353 | } |
| 354 | |
| 355 | /** |
| 356 | * The {@link android.os.UserHandle} for whom this notification is intended. |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 357 | */ |
| 358 | public UserHandle getUser() { |
| 359 | return user; |
| 360 | } |
| 361 | |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 362 | /** |
| 363 | * The time (in {@link System#currentTimeMillis} time) the notification was posted, |
Daniel Sandler | e6f7f2e | 2013-04-25 15:44:16 -0400 | [diff] [blame] | 364 | * which may be different than {@link android.app.Notification#when}. |
| 365 | */ |
| 366 | public long getPostTime() { |
| 367 | return postTime; |
| 368 | } |
| 369 | |
John Spurlock | a429429 | 2014-03-24 18:02:32 -0400 | [diff] [blame] | 370 | /** |
| 371 | * A unique instance key for this notification record. |
| 372 | */ |
| 373 | public String getKey() { |
| 374 | return key; |
| 375 | } |
Chris Wren | 1031c97 | 2014-07-23 13:11:45 +0000 | [diff] [blame] | 376 | |
| 377 | /** |
| 378 | * A key that indicates the group with which this message ranks. |
| 379 | */ |
| 380 | public String getGroupKey() { |
| 381 | return groupKey; |
| 382 | } |
Dan Sandler | 68079d5 | 2015-07-22 10:45:30 -0400 | [diff] [blame] | 383 | |
| 384 | /** |
Chris Wren | b392179 | 2017-06-01 13:34:46 -0400 | [diff] [blame] | 385 | * The ID passed to setGroup(), or the override, or null. |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 386 | * |
Chris Wren | b392179 | 2017-06-01 13:34:46 -0400 | [diff] [blame] | 387 | * @hide |
| 388 | */ |
| 389 | public String getGroup() { |
| 390 | if (overrideGroupKey != null) { |
| 391 | return overrideGroupKey; |
| 392 | } |
| 393 | return getNotification().getGroup(); |
| 394 | } |
| 395 | |
| 396 | /** |
Julia Reynolds | e46bb37 | 2016-03-17 11:05:58 -0400 | [diff] [blame] | 397 | * Sets the override group key. |
| 398 | */ |
| 399 | public void setOverrideGroupKey(String overrideGroupKey) { |
| 400 | this.overrideGroupKey = overrideGroupKey; |
| 401 | groupKey = groupKey(); |
| 402 | } |
| 403 | |
| 404 | /** |
| 405 | * Returns the override group key. |
| 406 | */ |
| 407 | public String getOverrideGroupKey() { |
| 408 | return overrideGroupKey; |
| 409 | } |
| 410 | |
| 411 | /** |
Dan Sandler | 68079d5 | 2015-07-22 10:45:30 -0400 | [diff] [blame] | 412 | * @hide |
| 413 | */ |
Amin Shaikh | c3f0b06 | 2019-02-12 19:00:17 -0500 | [diff] [blame] | 414 | public void clearPackageContext() { |
| 415 | mContext = null; |
| 416 | } |
| 417 | |
| 418 | /** |
| 419 | * @hide |
| 420 | */ |
Will Brockman | cfd9830 | 2020-01-29 15:57:30 -0500 | [diff] [blame] | 421 | public InstanceId getInstanceId() { |
| 422 | return mInstanceId; |
| 423 | } |
| 424 | |
| 425 | /** |
| 426 | * @hide |
| 427 | */ |
| 428 | public void setInstanceId(InstanceId instanceId) { |
| 429 | mInstanceId = instanceId; |
| 430 | } |
| 431 | |
| 432 | /** |
| 433 | * @hide |
| 434 | */ |
Mathew Inwood | e380737 | 2018-08-10 09:51:03 +0100 | [diff] [blame] | 435 | @UnsupportedAppUsage |
Dan Sandler | 68079d5 | 2015-07-22 10:45:30 -0400 | [diff] [blame] | 436 | public Context getPackageContext(Context context) { |
| 437 | if (mContext == null) { |
| 438 | try { |
| 439 | ApplicationInfo ai = context.getPackageManager() |
Amith Yamasani | 0d1fd8d | 2016-10-12 14:21:51 -0700 | [diff] [blame] | 440 | .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, |
| 441 | getUserId()); |
Dan Sandler | 68079d5 | 2015-07-22 10:45:30 -0400 | [diff] [blame] | 442 | mContext = context.createApplicationContext(ai, |
| 443 | Context.CONTEXT_RESTRICTED); |
| 444 | } catch (PackageManager.NameNotFoundException e) { |
| 445 | mContext = null; |
| 446 | } |
| 447 | } |
| 448 | if (mContext == null) { |
| 449 | mContext = context; |
| 450 | } |
| 451 | return mContext; |
| 452 | } |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 453 | |
| 454 | /** |
| 455 | * Returns a LogMaker that contains all basic information of the notification. |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 456 | * |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 457 | * @hide |
| 458 | */ |
| 459 | public LogMaker getLogMaker() { |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 460 | LogMaker logMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN).setPackageName(getPackageName()) |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 461 | .addTaggedData(MetricsEvent.NOTIFICATION_ID, getId()) |
| 462 | .addTaggedData(MetricsEvent.NOTIFICATION_TAG, getTag()) |
Will Brockman | 0ed07ca | 2019-03-08 11:45:34 -0500 | [diff] [blame] | 463 | .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag()) |
| 464 | .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag()) |
| 465 | .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY, |
| 466 | getNotification().isGroupSummary() ? 1 : 0) |
| 467 | .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CATEGORY, |
| 468 | getNotification().category); |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 469 | if (getNotification().extras != null) { |
| 470 | // Log the style used, if present. We only log the hash here, as notification log |
| 471 | // events are frequent, while there are few styles (hence low chance of collisions). |
| 472 | String template = getNotification().extras.getString(Notification.EXTRA_TEMPLATE); |
| 473 | if (template != null && !template.isEmpty()) { |
| 474 | logMaker.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_STYLE, |
| 475 | template.hashCode()); |
| 476 | } |
| 477 | ArrayList<Person> people = getNotification().extras.getParcelableArrayList( |
| 478 | Notification.EXTRA_PEOPLE_LIST); |
| 479 | if (people != null && !people.isEmpty()) { |
| 480 | logMaker.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_PEOPLE, people.size()); |
| 481 | } |
| 482 | } |
| 483 | return logMaker; |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 484 | } |
| 485 | |
Julia Reynolds | 7c26752 | 2020-01-16 11:26:41 -0500 | [diff] [blame] | 486 | /** |
| 487 | * @hide |
| 488 | */ |
| 489 | public String getShortcutId(Context context) { |
| 490 | String conversationId = getNotification().getShortcutId(); |
Julia Reynolds | e24faa2 | 2020-04-02 12:44:47 -0400 | [diff] [blame] | 491 | if (TextUtils.isEmpty(conversationId) |
| 492 | && (Settings.Global.getInt(context.getContentResolver(), |
| 493 | Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0) == 0) |
| 494 | && getNotification().getNotificationStyle() == Notification.MessagingStyle.class) { |
Julia Reynolds | 7c26752 | 2020-01-16 11:26:41 -0500 | [diff] [blame] | 495 | conversationId = getId() + getTag() + PLACEHOLDER_CONVERSATION_ID; |
| 496 | } |
| 497 | return conversationId; |
| 498 | } |
| 499 | |
Will Brockman | 2b6959e | 2020-01-22 09:59:50 -0500 | [diff] [blame] | 500 | /** |
| 501 | * Returns a probably-unique string based on the notification's group name, |
| 502 | * with no more than MAX_LOG_TAG_LENGTH characters. |
| 503 | * @return String based on group name of notification. |
| 504 | * @hide |
| 505 | */ |
| 506 | public String getGroupLogTag() { |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 507 | return shortenTag(getGroup()); |
| 508 | } |
| 509 | |
Will Brockman | 2b6959e | 2020-01-22 09:59:50 -0500 | [diff] [blame] | 510 | /** |
| 511 | * Returns a probably-unique string based on the notification's channel ID, |
| 512 | * with no more than MAX_LOG_TAG_LENGTH characters. |
| 513 | * @return String based on channel ID of notification. |
| 514 | * @hide |
| 515 | */ |
| 516 | public String getChannelIdLogTag() { |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 517 | if (notification.getChannelId() == null) { |
| 518 | return null; |
| 519 | } |
| 520 | return shortenTag(notification.getChannelId()); |
| 521 | } |
| 522 | |
| 523 | // Make logTag with max size MAX_LOG_TAG_LENGTH. |
| 524 | // For shorter or equal tags, returns the tag. |
| 525 | // For longer tags, truncate the tag and append a hash of the full tag to |
| 526 | // fill the maximum size. |
| 527 | private String shortenTag(String logTag) { |
| 528 | if (logTag == null || logTag.length() <= MAX_LOG_TAG_LENGTH) { |
| 529 | return logTag; |
| 530 | } |
| 531 | String hash = Integer.toHexString(logTag.hashCode()); |
| 532 | return logTag.substring(0, MAX_LOG_TAG_LENGTH - hash.length() - 1) + "-" |
Will Brockman | c22772c | 2019-06-14 14:55:31 -0400 | [diff] [blame] | 533 | + hash; |
Eyal Posener | a9cf9c7 | 2018-12-18 16:23:54 +0200 | [diff] [blame] | 534 | } |
Joe Onorato | 18e69df | 2010-05-17 22:26:12 -0700 | [diff] [blame] | 535 | } |