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