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