Home | History | Annotate | Download | only in notification
      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 */
     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 */
     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 
     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 
     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 
    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 
    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      */
    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      */
    156     public boolean isAppGroup() {
    157         if (getNotification().getGroup() != null || getNotification().getSortKey() != null) {
    158             return true;
    159         }
    160         return false;
    161     }
    162 
    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 
    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      */
    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
    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
    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      */
    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      */
    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      */
    252     public int getUserId() {
    253         return this.user.getIdentifier();
    254     }
    255 
    256     /** The package of the app that posted the notification. */
    257     public String getPackageName() {
    258         return pkg;
    259     }
    260 
    261     /** The id supplied to {@link android.app.NotificationManager#notify(int,Notification)}. */
    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. */
    268     public String getTag() {
    269         return tag;
    270     }
    271 
    272     /** The notifying app's calling uid. @hide */
    273     public int getUid() {
    274         return uid;
    275     }
    276 
    277     /** The package used for AppOps tracking. @hide */
    278     public String getOpPkg() {
    279         return opPkg;
    280     }
    281 
    282     /** @hide */
    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)}. */
    289     public Notification getNotification() {
    290         return notification;
    291     }
    292 
    293     /**
    294      * The {@link android.os.UserHandle} for whom this notification is intended.
    295      */
    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      */
    303     public long getPostTime() {
    304         return postTime;
    305     }
    306 
    307     /**
    308      * A unique instance key for this notification record.
    309      */
    310     public String getKey() {
    311         return key;
    312     }
    313 
    314     /**
    315      * A key that indicates the group with which this message ranks.
    316      */
    317     public String getGroupKey() {
    318         return groupKey;
    319     }
    320 
    321     /**
    322      * Sets the override group key.
    323      */
    324     public void setOverrideGroupKey(String overrideGroupKey) {
    325         this.overrideGroupKey = overrideGroupKey;
    326         groupKey = groupKey();
    327     }
    328 
    329     /**
    330      * Returns the override group key.
    331      */
    332     public String getOverrideGroupKey() {
    333         return overrideGroupKey;
    334     }
    335 
    336     /**
    337      * @hide
    338      */
    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