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.os.Parcel;
21 import android.os.Parcelable;
22 import android.os.UserHandle;
23 
24 /**
25  * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including
26  * the status bar and any {@link android.service.notification.NotificationListenerService}s.
27  */
28 public class StatusBarNotification implements Parcelable {
29     private final String pkg;
30     private final int id;
31     private final String tag;
32     private final String key;
33     private final String groupKey;
34 
35     private final int uid;
36     private final String opPkg;
37     private final int initialPid;
38     private final Notification notification;
39     private final UserHandle user;
40     private final long postTime;
41 
42     private final int score;
43 
44     /** @hide */
StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, int score, Notification notification, UserHandle user)45     public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
46             int initialPid, int score, Notification notification, UserHandle user) {
47         this(pkg, opPkg, id, tag, uid, initialPid, score, notification, user,
48                 System.currentTimeMillis());
49     }
50 
StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, int score, Notification notification, UserHandle user, long postTime)51     public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
52             int initialPid, int score, Notification notification, UserHandle user,
53             long postTime) {
54         if (pkg == null) throw new NullPointerException();
55         if (notification == null) throw new NullPointerException();
56 
57         this.pkg = pkg;
58         this.opPkg = opPkg;
59         this.id = id;
60         this.tag = tag;
61         this.uid = uid;
62         this.initialPid = initialPid;
63         this.score = score;
64         this.notification = notification;
65         this.user = user;
66         this.postTime = postTime;
67         this.key = key();
68         this.groupKey = groupKey();
69     }
70 
StatusBarNotification(Parcel in)71     public StatusBarNotification(Parcel in) {
72         this.pkg = in.readString();
73         this.opPkg = in.readString();
74         this.id = in.readInt();
75         if (in.readInt() != 0) {
76             this.tag = in.readString();
77         } else {
78             this.tag = null;
79         }
80         this.uid = in.readInt();
81         this.initialPid = in.readInt();
82         this.score = in.readInt();
83         this.notification = new Notification(in);
84         this.user = UserHandle.readFromParcel(in);
85         this.postTime = in.readLong();
86         this.key = key();
87         this.groupKey = groupKey();
88     }
89 
key()90     private String key() {
91         return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
92     }
93 
groupKey()94     private String groupKey() {
95         final String group = getNotification().getGroup();
96         final String sortKey = getNotification().getSortKey();
97         if (group == null && sortKey == null) {
98             // a group of one
99             return key;
100         }
101         return user.getIdentifier() + "|" + pkg + "|" +
102                 (group == null
103                         ? "p:" + notification.priority
104                         : "g:" + group);
105     }
106 
writeToParcel(Parcel out, int flags)107     public void writeToParcel(Parcel out, int flags) {
108         out.writeString(this.pkg);
109         out.writeString(this.opPkg);
110         out.writeInt(this.id);
111         if (this.tag != null) {
112             out.writeInt(1);
113             out.writeString(this.tag);
114         } else {
115             out.writeInt(0);
116         }
117         out.writeInt(this.uid);
118         out.writeInt(this.initialPid);
119         out.writeInt(this.score);
120         this.notification.writeToParcel(out, flags);
121         user.writeToParcel(out, flags);
122 
123         out.writeLong(this.postTime);
124     }
125 
describeContents()126     public int describeContents() {
127         return 0;
128     }
129 
130     public static final Parcelable.Creator<StatusBarNotification> CREATOR
131             = new Parcelable.Creator<StatusBarNotification>()
132     {
133         public StatusBarNotification createFromParcel(Parcel parcel)
134         {
135             return new StatusBarNotification(parcel);
136         }
137 
138         public StatusBarNotification[] newArray(int size)
139         {
140             return new StatusBarNotification[size];
141         }
142     };
143 
144     /**
145      * @hide
146      */
cloneLight()147     public StatusBarNotification cloneLight() {
148         final Notification no = new Notification();
149         this.notification.cloneInto(no, false); // light copy
150         return new StatusBarNotification(this.pkg, this.opPkg,
151                 this.id, this.tag, this.uid, this.initialPid,
152                 this.score, no, this.user, this.postTime);
153     }
154 
155     @Override
clone()156     public StatusBarNotification clone() {
157         return new StatusBarNotification(this.pkg, this.opPkg,
158                 this.id, this.tag, this.uid, this.initialPid,
159                 this.score, this.notification.clone(), this.user, this.postTime);
160     }
161 
162     @Override
toString()163     public String toString() {
164         return String.format(
165                 "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
166                 this.pkg, this.user, this.id, this.tag,
167                 this.score, this.key, this.notification);
168     }
169 
170     /** Convenience method to check the notification's flags for
171      * {@link Notification#FLAG_ONGOING_EVENT}.
172      */
isOngoing()173     public boolean isOngoing() {
174         return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
175     }
176 
177     /** Convenience method to check the notification's flags for
178      * either {@link Notification#FLAG_ONGOING_EVENT} or
179      * {@link Notification#FLAG_NO_CLEAR}.
180      */
isClearable()181     public boolean isClearable() {
182         return ((notification.flags & Notification.FLAG_ONGOING_EVENT) == 0)
183                 && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
184     }
185 
186     /**
187      * Returns a userHandle for the instance of the app that posted this notification.
188      *
189      * @deprecated Use {@link #getUser()} instead.
190      */
getUserId()191     public int getUserId() {
192         return this.user.getIdentifier();
193     }
194 
195     /** The package of the app that posted the notification. */
getPackageName()196     public String getPackageName() {
197         return pkg;
198     }
199 
200     /** The id supplied to {@link android.app.NotificationManager#notify(int,Notification)}. */
getId()201     public int getId() {
202         return id;
203     }
204 
205     /** The tag supplied to {@link android.app.NotificationManager#notify(int,Notification)},
206      * or null if no tag was specified. */
getTag()207     public String getTag() {
208         return tag;
209     }
210 
211     /** The notifying app's calling uid. @hide */
getUid()212     public int getUid() {
213         return uid;
214     }
215 
216     /** The package used for AppOps tracking. @hide */
getOpPkg()217     public String getOpPkg() {
218         return opPkg;
219     }
220 
221     /** @hide */
getInitialPid()222     public int getInitialPid() {
223         return initialPid;
224     }
225 
226     /** The {@link android.app.Notification} supplied to
227      * {@link android.app.NotificationManager#notify(int,Notification)}. */
getNotification()228     public Notification getNotification() {
229         return notification;
230     }
231 
232     /**
233      * The {@link android.os.UserHandle} for whom this notification is intended.
234      */
getUser()235     public UserHandle getUser() {
236         return user;
237     }
238 
239     /** The time (in {@link System#currentTimeMillis} time) the notification was posted,
240      * which may be different than {@link android.app.Notification#when}.
241      */
getPostTime()242     public long getPostTime() {
243         return postTime;
244     }
245 
246     /** @hide */
getScore()247     public int getScore() {
248         return score;
249     }
250 
251     /**
252      * A unique instance key for this notification record.
253      */
getKey()254     public String getKey() {
255         return key;
256     }
257 
258     /**
259      * A key that indicates the group with which this message ranks.
260      */
getGroupKey()261     public String getGroupKey() {
262         return groupKey;
263     }
264 }
265