• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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