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 17 package android.service.notification; 18 19 import android.app.Notification; 20 import android.app.NotificationChannel; 21 import android.content.Context; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageManager; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.os.UserHandle; 27 28 /** 29 * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including 30 * the status bar and any {@link android.service.notification.NotificationListenerService}s. 31 */ 32 public class StatusBarNotification implements Parcelable { 33 private final String pkg; 34 private final int id; 35 private final String tag; 36 private final String key; 37 private String groupKey; 38 private String overrideGroupKey; 39 40 private final int uid; 41 private final String opPkg; 42 private final int initialPid; 43 private final Notification notification; 44 private final UserHandle user; 45 private final long postTime; 46 47 private Context mContext; // used for inflation & icon expansion 48 49 /** @hide */ StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, Notification notification, UserHandle user, String overrideGroupKey, long postTime)50 public StatusBarNotification(String pkg, String opPkg, int id, 51 String tag, int uid, int initialPid, Notification notification, UserHandle user, 52 String overrideGroupKey, long postTime) { 53 if (pkg == null) throw new NullPointerException(); 54 if (notification == null) throw new NullPointerException(); 55 56 this.pkg = pkg; 57 this.opPkg = opPkg; 58 this.id = id; 59 this.tag = tag; 60 this.uid = uid; 61 this.initialPid = initialPid; 62 this.notification = notification; 63 this.user = user; 64 this.postTime = postTime; 65 this.overrideGroupKey = overrideGroupKey; 66 this.key = key(); 67 this.groupKey = groupKey(); 68 } 69 70 /** 71 * @deprecated Non-system apps should not need to create StatusBarNotifications. 72 */ 73 @Deprecated StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, int score, Notification notification, UserHandle user, long postTime)74 public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, 75 int initialPid, int score, Notification notification, UserHandle user, 76 long postTime) { 77 if (pkg == null) throw new NullPointerException(); 78 if (notification == null) throw new NullPointerException(); 79 80 this.pkg = pkg; 81 this.opPkg = opPkg; 82 this.id = id; 83 this.tag = tag; 84 this.uid = uid; 85 this.initialPid = initialPid; 86 this.notification = notification; 87 this.user = user; 88 this.postTime = postTime; 89 this.key = key(); 90 this.groupKey = groupKey(); 91 } 92 StatusBarNotification(Parcel in)93 public StatusBarNotification(Parcel in) { 94 this.pkg = in.readString(); 95 this.opPkg = in.readString(); 96 this.id = in.readInt(); 97 if (in.readInt() != 0) { 98 this.tag = in.readString(); 99 } else { 100 this.tag = null; 101 } 102 this.uid = in.readInt(); 103 this.initialPid = in.readInt(); 104 this.notification = new Notification(in); 105 this.user = UserHandle.readFromParcel(in); 106 this.postTime = in.readLong(); 107 if (in.readInt() != 0) { 108 this.overrideGroupKey = in.readString(); 109 } else { 110 this.overrideGroupKey = null; 111 } 112 this.key = key(); 113 this.groupKey = groupKey(); 114 } 115 key()116 private String key() { 117 String sbnKey = user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid; 118 if (overrideGroupKey != null && getNotification().isGroupSummary()) { 119 sbnKey = sbnKey + "|" + overrideGroupKey; 120 } 121 return sbnKey; 122 } 123 groupKey()124 private String groupKey() { 125 if (overrideGroupKey != null) { 126 return user.getIdentifier() + "|" + pkg + "|" + "g:" + overrideGroupKey; 127 } 128 final String group = getNotification().getGroup(); 129 final String sortKey = getNotification().getSortKey(); 130 if (group == null && sortKey == null) { 131 // a group of one 132 return key; 133 } 134 return user.getIdentifier() + "|" + pkg + "|" + 135 (group == null 136 ? "c:" + notification.getChannelId() 137 : "g:" + group); 138 } 139 140 /** 141 * Returns true if this notification is part of a group. 142 */ isGroup()143 public boolean isGroup() { 144 if (overrideGroupKey != null || isAppGroup()) { 145 return true; 146 } 147 return false; 148 } 149 150 /** 151 * Returns true if application asked that this notification be part of a group. 152 * @hide 153 */ isAppGroup()154 public boolean isAppGroup() { 155 if (getNotification().getGroup() != null || getNotification().getSortKey() != null) { 156 return true; 157 } 158 return false; 159 } 160 writeToParcel(Parcel out, int flags)161 public void writeToParcel(Parcel out, int flags) { 162 out.writeString(this.pkg); 163 out.writeString(this.opPkg); 164 out.writeInt(this.id); 165 if (this.tag != null) { 166 out.writeInt(1); 167 out.writeString(this.tag); 168 } else { 169 out.writeInt(0); 170 } 171 out.writeInt(this.uid); 172 out.writeInt(this.initialPid); 173 this.notification.writeToParcel(out, flags); 174 user.writeToParcel(out, flags); 175 176 out.writeLong(this.postTime); 177 if (this.overrideGroupKey != null) { 178 out.writeInt(1); 179 out.writeString(this.overrideGroupKey); 180 } else { 181 out.writeInt(0); 182 } 183 } 184 describeContents()185 public int describeContents() { 186 return 0; 187 } 188 189 public static final Parcelable.Creator<StatusBarNotification> CREATOR 190 = new Parcelable.Creator<StatusBarNotification>() 191 { 192 public StatusBarNotification createFromParcel(Parcel parcel) 193 { 194 return new StatusBarNotification(parcel); 195 } 196 197 public StatusBarNotification[] newArray(int size) 198 { 199 return new StatusBarNotification[size]; 200 } 201 }; 202 203 /** 204 * @hide 205 */ cloneLight()206 public StatusBarNotification cloneLight() { 207 final Notification no = new Notification(); 208 this.notification.cloneInto(no, false); // light copy 209 return new StatusBarNotification(this.pkg, this.opPkg, 210 this.id, this.tag, this.uid, this.initialPid, 211 no, this.user, this.overrideGroupKey, this.postTime); 212 } 213 214 @Override clone()215 public StatusBarNotification clone() { 216 return new StatusBarNotification(this.pkg, this.opPkg, 217 this.id, this.tag, this.uid, this.initialPid, 218 this.notification.clone(), this.user, this.overrideGroupKey, this.postTime); 219 } 220 221 @Override toString()222 public String toString() { 223 return String.format( 224 "StatusBarNotification(pkg=%s user=%s id=%d tag=%s key=%s: %s)", 225 this.pkg, this.user, this.id, this.tag, 226 this.key, this.notification); 227 } 228 229 /** Convenience method to check the notification's flags for 230 * {@link Notification#FLAG_ONGOING_EVENT}. 231 */ isOngoing()232 public boolean isOngoing() { 233 return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0; 234 } 235 236 /** Convenience method to check the notification's flags for 237 * either {@link Notification#FLAG_ONGOING_EVENT} or 238 * {@link Notification#FLAG_NO_CLEAR}. 239 */ isClearable()240 public boolean isClearable() { 241 return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) 242 && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0); 243 } 244 245 /** 246 * Returns a userid for whom this notification is intended. 247 * 248 * @deprecated Use {@link #getUser()} instead. 249 */ 250 @Deprecated getUserId()251 public int getUserId() { 252 return this.user.getIdentifier(); 253 } 254 255 /** The package of the app that posted the notification. */ getPackageName()256 public String getPackageName() { 257 return pkg; 258 } 259 260 /** The id supplied to {@link android.app.NotificationManager#notify(int,Notification)}. */ getId()261 public int getId() { 262 return id; 263 } 264 265 /** The tag supplied to {@link android.app.NotificationManager#notify(int,Notification)}, 266 * or null if no tag was specified. */ getTag()267 public String getTag() { 268 return tag; 269 } 270 271 /** The notifying app's calling uid. @hide */ getUid()272 public int getUid() { 273 return uid; 274 } 275 276 /** The package used for AppOps tracking. @hide */ getOpPkg()277 public String getOpPkg() { 278 return opPkg; 279 } 280 281 /** @hide */ getInitialPid()282 public int getInitialPid() { 283 return initialPid; 284 } 285 286 /** The {@link android.app.Notification} supplied to 287 * {@link android.app.NotificationManager#notify(int,Notification)}. */ getNotification()288 public Notification getNotification() { 289 return notification; 290 } 291 292 /** 293 * The {@link android.os.UserHandle} for whom this notification is intended. 294 */ getUser()295 public UserHandle getUser() { 296 return user; 297 } 298 299 /** The time (in {@link System#currentTimeMillis} time) the notification was posted, 300 * which may be different than {@link android.app.Notification#when}. 301 */ getPostTime()302 public long getPostTime() { 303 return postTime; 304 } 305 306 /** 307 * A unique instance key for this notification record. 308 */ getKey()309 public String getKey() { 310 return key; 311 } 312 313 /** 314 * A key that indicates the group with which this message ranks. 315 */ getGroupKey()316 public String getGroupKey() { 317 return groupKey; 318 } 319 320 /** 321 * The ID passed to setGroup(), or the override, or null. 322 * @hide 323 */ getGroup()324 public String getGroup() { 325 if (overrideGroupKey != null) { 326 return overrideGroupKey; 327 } 328 return getNotification().getGroup(); 329 } 330 331 /** 332 * Sets the override group key. 333 */ setOverrideGroupKey(String overrideGroupKey)334 public void setOverrideGroupKey(String overrideGroupKey) { 335 this.overrideGroupKey = overrideGroupKey; 336 groupKey = groupKey(); 337 } 338 339 /** 340 * Returns the override group key. 341 */ getOverrideGroupKey()342 public String getOverrideGroupKey() { 343 return overrideGroupKey; 344 } 345 346 /** 347 * @hide 348 */ getPackageContext(Context context)349 public Context getPackageContext(Context context) { 350 if (mContext == null) { 351 try { 352 ApplicationInfo ai = context.getPackageManager() 353 .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, 354 getUserId()); 355 mContext = context.createApplicationContext(ai, 356 Context.CONTEXT_RESTRICTED); 357 } catch (PackageManager.NameNotFoundException e) { 358 mContext = null; 359 } 360 } 361 if (mContext == null) { 362 mContext = context; 363 } 364 return mContext; 365 } 366 } 367