Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2007 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.app;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.annotation.SdkConstant;
     22 import android.app.Notification.Builder;
     23 import android.content.ComponentName;
     24 import android.content.Context;
     25 import android.content.pm.ParceledListSlice;
     26 import android.graphics.drawable.Icon;
     27 import android.net.Uri;
     28 import android.os.Build;
     29 import android.os.Bundle;
     30 import android.os.Handler;
     31 import android.os.IBinder;
     32 import android.os.Parcel;
     33 import android.os.Parcelable;
     34 import android.os.RemoteException;
     35 import android.os.ServiceManager;
     36 import android.os.StrictMode;
     37 import android.os.UserHandle;
     38 import android.provider.Settings.Global;
     39 import android.service.notification.IConditionListener;
     40 import android.service.notification.StatusBarNotification;
     41 import android.service.notification.ZenModeConfig;
     42 import android.util.ArraySet;
     43 import android.util.Log;
     44 
     45 import java.util.Objects;
     46 import java.util.List;
     47 
     48 /**
     49  * Class to notify the user of events that happen.  This is how you tell
     50  * the user that something has happened in the background. {@more}
     51  *
     52  * Notifications can take different forms:
     53  * <ul>
     54  *      <li>A persistent icon that goes in the status bar and is accessible
     55  *          through the launcher, (when the user selects it, a designated Intent
     56  *          can be launched),</li>
     57  *      <li>Turning on or flashing LEDs on the device, or</li>
     58  *      <li>Alerting the user by flashing the backlight, playing a sound,
     59  *          or vibrating.</li>
     60  * </ul>
     61  *
     62  * <p>
     63  * Each of the notify methods takes an int id parameter and optionally a
     64  * {@link String} tag parameter, which may be {@code null}.  These parameters
     65  * are used to form a pair (tag, id), or ({@code null}, id) if tag is
     66  * unspecified.  This pair identifies this notification from your app to the
     67  * system, so that pair should be unique within your app.  If you call one
     68  * of the notify methods with a (tag, id) pair that is currently active and
     69  * a new set of notification parameters, it will be updated.  For example,
     70  * if you pass a new status bar icon, the old icon in the status bar will
     71  * be replaced with the new one.  This is also the same tag and id you pass
     72  * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
     73  * this notification.
     74  *
     75  * <p>
     76  * You do not instantiate this class directly; instead, retrieve it through
     77  * {@link android.content.Context#getSystemService}.
     78  *
     79  * <div class="special reference">
     80  * <h3>Developer Guides</h3>
     81  * <p>For a guide to creating notifications, read the
     82  * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
     83  * developer guide.</p>
     84  * </div>
     85  *
     86  * @see android.app.Notification
     87  * @see android.content.Context#getSystemService
     88  */
     89 public class NotificationManager
     90 {
     91     private static String TAG = "NotificationManager";
     92     private static boolean localLOGV = false;
     93 
     94     /**
     95      * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
     96      * This broadcast is only sent to registered receivers.
     97      *
     98      * @hide
     99      */
    100     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    101     public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED
    102             = "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED";
    103 
    104     /**
    105      * Intent that is broadcast when the state of {@link #isNotificationPolicyAccessGranted()}
    106      * changes.
    107      *
    108      * This broadcast is only sent to registered receivers, and only to the apps that have changed.
    109      */
    110     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    111     public static final String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED
    112             = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
    113 
    114     /**
    115      * Intent that is broadcast when the state of getNotificationPolicy() changes.
    116      * This broadcast is only sent to registered receivers.
    117      */
    118     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    119     public static final String ACTION_NOTIFICATION_POLICY_CHANGED
    120             = "android.app.action.NOTIFICATION_POLICY_CHANGED";
    121 
    122     /**
    123      * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
    124      * This broadcast is only sent to registered receivers.
    125      */
    126     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    127     public static final String ACTION_INTERRUPTION_FILTER_CHANGED
    128             = "android.app.action.INTERRUPTION_FILTER_CHANGED";
    129 
    130     /**
    131      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    132      *     Normal interruption filter.
    133      */
    134     public static final int INTERRUPTION_FILTER_ALL = 1;
    135 
    136     /**
    137      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    138      *     Priority interruption filter.
    139      */
    140     public static final int INTERRUPTION_FILTER_PRIORITY = 2;
    141 
    142     /**
    143      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    144      *     No interruptions filter.
    145      */
    146     public static final int INTERRUPTION_FILTER_NONE = 3;
    147 
    148     /**
    149      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    150      *     Alarms only interruption filter.
    151      */
    152     public static final int INTERRUPTION_FILTER_ALARMS = 4;
    153 
    154     /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when
    155      * the value is unavailable for any reason.
    156      */
    157     public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
    158 
    159     private static INotificationManager sService;
    160 
    161     /** @hide */
    162     static public INotificationManager getService()
    163     {
    164         if (sService != null) {
    165             return sService;
    166         }
    167         IBinder b = ServiceManager.getService("notification");
    168         sService = INotificationManager.Stub.asInterface(b);
    169         return sService;
    170     }
    171 
    172     /*package*/ NotificationManager(Context context, Handler handler)
    173     {
    174         mContext = context;
    175     }
    176 
    177     /** {@hide} */
    178     public static NotificationManager from(Context context) {
    179         return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    180     }
    181 
    182     /**
    183      * Post a notification to be shown in the status bar. If a notification with
    184      * the same id has already been posted by your application and has not yet been canceled, it
    185      * will be replaced by the updated information.
    186      *
    187      * @param id An identifier for this notification unique within your
    188      *        application.
    189      * @param notification A {@link Notification} object describing what to show the user. Must not
    190      *        be null.
    191      */
    192     public void notify(int id, Notification notification)
    193     {
    194         notify(null, id, notification);
    195     }
    196 
    197     /**
    198      * Post a notification to be shown in the status bar. If a notification with
    199      * the same tag and id has already been posted by your application and has not yet been
    200      * canceled, it will be replaced by the updated information.
    201      *
    202      * @param tag A string identifier for this notification.  May be {@code null}.
    203      * @param id An identifier for this notification.  The pair (tag, id) must be unique
    204      *        within your application.
    205      * @param notification A {@link Notification} object describing what to
    206      *        show the user. Must not be null.
    207      */
    208     public void notify(String tag, int id, Notification notification)
    209     {
    210         int[] idOut = new int[1];
    211         INotificationManager service = getService();
    212         String pkg = mContext.getPackageName();
    213         if (notification.sound != null) {
    214             notification.sound = notification.sound.getCanonicalUri();
    215             if (StrictMode.vmFileUriExposureEnabled()) {
    216                 notification.sound.checkFileUriExposed("Notification.sound");
    217             }
    218         }
    219         fixLegacySmallIcon(notification, pkg);
    220         if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
    221             if (notification.getSmallIcon() == null) {
    222                 throw new IllegalArgumentException("Invalid notification (no valid small icon): "
    223                     + notification);
    224             }
    225         }
    226         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
    227         Notification stripped = notification.clone();
    228         Builder.stripForDelivery(stripped);
    229         try {
    230             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
    231                     stripped, idOut, UserHandle.myUserId());
    232             if (id != idOut[0]) {
    233                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
    234             }
    235         } catch (RemoteException e) {
    236         }
    237     }
    238 
    239     /**
    240      * @hide
    241      */
    242     public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
    243     {
    244         int[] idOut = new int[1];
    245         INotificationManager service = getService();
    246         String pkg = mContext.getPackageName();
    247         if (notification.sound != null) {
    248             notification.sound = notification.sound.getCanonicalUri();
    249             if (StrictMode.vmFileUriExposureEnabled()) {
    250                 notification.sound.checkFileUriExposed("Notification.sound");
    251             }
    252         }
    253         fixLegacySmallIcon(notification, pkg);
    254         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
    255         Notification stripped = notification.clone();
    256         Builder.stripForDelivery(stripped);
    257         try {
    258             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
    259                     stripped, idOut, user.getIdentifier());
    260             if (id != idOut[0]) {
    261                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
    262             }
    263         } catch (RemoteException e) {
    264         }
    265     }
    266 
    267     private void fixLegacySmallIcon(Notification n, String pkg) {
    268         if (n.getSmallIcon() == null && n.icon != 0) {
    269             n.setSmallIcon(Icon.createWithResource(pkg, n.icon));
    270         }
    271     }
    272 
    273     /**
    274      * Cancel a previously shown notification.  If it's transient, the view
    275      * will be hidden.  If it's persistent, it will be removed from the status
    276      * bar.
    277      */
    278     public void cancel(int id)
    279     {
    280         cancel(null, id);
    281     }
    282 
    283     /**
    284      * Cancel a previously shown notification.  If it's transient, the view
    285      * will be hidden.  If it's persistent, it will be removed from the status
    286      * bar.
    287      */
    288     public void cancel(String tag, int id)
    289     {
    290         INotificationManager service = getService();
    291         String pkg = mContext.getPackageName();
    292         if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
    293         try {
    294             service.cancelNotificationWithTag(pkg, tag, id, UserHandle.myUserId());
    295         } catch (RemoteException e) {
    296         }
    297     }
    298 
    299     /**
    300      * @hide
    301      */
    302     public void cancelAsUser(String tag, int id, UserHandle user)
    303     {
    304         INotificationManager service = getService();
    305         String pkg = mContext.getPackageName();
    306         if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
    307         try {
    308             service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
    309         } catch (RemoteException e) {
    310         }
    311     }
    312 
    313     /**
    314      * Cancel all previously shown notifications. See {@link #cancel} for the
    315      * detailed behavior.
    316      */
    317     public void cancelAll()
    318     {
    319         INotificationManager service = getService();
    320         String pkg = mContext.getPackageName();
    321         if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
    322         try {
    323             service.cancelAllNotifications(pkg, UserHandle.myUserId());
    324         } catch (RemoteException e) {
    325         }
    326     }
    327 
    328     /**
    329      * @hide
    330      */
    331     public ComponentName getEffectsSuppressor() {
    332         INotificationManager service = getService();
    333         try {
    334             return service.getEffectsSuppressor();
    335         } catch (RemoteException e) {
    336             return null;
    337         }
    338     }
    339 
    340     /**
    341      * @hide
    342      */
    343     public boolean matchesCallFilter(Bundle extras) {
    344         INotificationManager service = getService();
    345         try {
    346             return service.matchesCallFilter(extras);
    347         } catch (RemoteException e) {
    348             return false;
    349         }
    350     }
    351 
    352     /**
    353      * @hide
    354      */
    355     public boolean isSystemConditionProviderEnabled(String path) {
    356         INotificationManager service = getService();
    357         try {
    358             return service.isSystemConditionProviderEnabled(path);
    359         } catch (RemoteException e) {
    360             return false;
    361         }
    362     }
    363 
    364     /**
    365      * @hide
    366      */
    367     public void setZenMode(int mode, Uri conditionId, String reason) {
    368         INotificationManager service = getService();
    369         try {
    370             service.setZenMode(mode, conditionId, reason);
    371         } catch (RemoteException e) {
    372         }
    373     }
    374 
    375     /**
    376      * @hide
    377      */
    378     public boolean setZenModeConfig(ZenModeConfig config, String reason) {
    379         INotificationManager service = getService();
    380         try {
    381             return service.setZenModeConfig(config, reason);
    382         } catch (RemoteException e) {
    383             return false;
    384         }
    385     }
    386 
    387     /**
    388      * @hide
    389      */
    390     public void requestZenModeConditions(IConditionListener listener, int relevance) {
    391         INotificationManager service = getService();
    392         try {
    393             service.requestZenModeConditions(listener, relevance);
    394         } catch (RemoteException e) {
    395         }
    396     }
    397 
    398     /**
    399      * @hide
    400      */
    401     public int getZenMode() {
    402         INotificationManager service = getService();
    403         try {
    404             return service.getZenMode();
    405         } catch (RemoteException e) {
    406         }
    407         return Global.ZEN_MODE_OFF;
    408     }
    409 
    410     /**
    411      * @hide
    412      */
    413     public ZenModeConfig getZenModeConfig() {
    414         INotificationManager service = getService();
    415         try {
    416             return service.getZenModeConfig();
    417         } catch (RemoteException e) {
    418         }
    419         return null;
    420     }
    421 
    422     /**
    423      * Checks the ability to read/modify notification policy for the calling package.
    424      *
    425      * <p>
    426      * Returns true if the calling package can read/modify notification policy.
    427      *
    428      * <p>
    429      * Request policy access by sending the user to the activity that matches the system intent
    430      * action {@link android.provider.Settings#ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS}.
    431      *
    432      * <p>
    433      * Use {@link #ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED} to listen for
    434      * user grant or denial of this access.
    435      */
    436     public boolean isNotificationPolicyAccessGranted() {
    437         INotificationManager service = getService();
    438         try {
    439             return service.isNotificationPolicyAccessGranted(mContext.getOpPackageName());
    440         } catch (RemoteException e) {
    441         }
    442         return false;
    443     }
    444 
    445     /** @hide */
    446     public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
    447         INotificationManager service = getService();
    448         try {
    449             return service.isNotificationPolicyAccessGrantedForPackage(pkg);
    450         } catch (RemoteException e) {
    451         }
    452         return false;
    453     }
    454 
    455     /**
    456      * Gets the current notification policy.
    457      *
    458      * <p>
    459      * Only available if policy access is granted to this package.
    460      * See {@link #isNotificationPolicyAccessGranted}.
    461      */
    462     public Policy getNotificationPolicy() {
    463         INotificationManager service = getService();
    464         try {
    465             return service.getNotificationPolicy(mContext.getOpPackageName());
    466         } catch (RemoteException e) {
    467         }
    468         return null;
    469     }
    470 
    471     /**
    472      * Sets the current notification policy.
    473      *
    474      * <p>
    475      * Only available if policy access is granted to this package.
    476      * See {@link #isNotificationPolicyAccessGranted}.
    477      *
    478      * @param policy The new desired policy.
    479      */
    480     public void setNotificationPolicy(@NonNull Policy policy) {
    481         checkRequired("policy", policy);
    482         INotificationManager service = getService();
    483         try {
    484             service.setNotificationPolicy(mContext.getOpPackageName(), policy);
    485         } catch (RemoteException e) {
    486         }
    487     }
    488 
    489     /** @hide */
    490     public void setNotificationPolicyAccessGranted(String pkg, boolean granted) {
    491         INotificationManager service = getService();
    492         try {
    493             service.setNotificationPolicyAccessGranted(pkg, granted);
    494         } catch (RemoteException e) {
    495         }
    496     }
    497 
    498     /** @hide */
    499     public ArraySet<String> getPackagesRequestingNotificationPolicyAccess() {
    500         INotificationManager service = getService();
    501         try {
    502             final String[] pkgs = service.getPackagesRequestingNotificationPolicyAccess();
    503             if (pkgs != null && pkgs.length > 0) {
    504                 final ArraySet<String> rt = new ArraySet<>(pkgs.length);
    505                 for (int i = 0; i < pkgs.length; i++) {
    506                     rt.add(pkgs[i]);
    507                 }
    508                 return rt;
    509             }
    510         } catch (RemoteException e) {
    511         }
    512         return new ArraySet<String>();
    513     }
    514 
    515     private Context mContext;
    516 
    517     private static void checkRequired(String name, Object value) {
    518         if (value == null) {
    519             throw new IllegalArgumentException(name + " is required");
    520         }
    521     }
    522 
    523     /**
    524      * Notification policy configuration.  Represents user-preferences for notification
    525      * filtering and prioritization.
    526      */
    527     public static class Policy implements android.os.Parcelable {
    528         /** Reminder notifications are prioritized. */
    529         public static final int PRIORITY_CATEGORY_REMINDERS = 1 << 0;
    530         /** Event notifications are prioritized. */
    531         public static final int PRIORITY_CATEGORY_EVENTS = 1 << 1;
    532         /** Message notifications are prioritized. */
    533         public static final int PRIORITY_CATEGORY_MESSAGES = 1 << 2;
    534         /** Calls are prioritized. */
    535         public static final int PRIORITY_CATEGORY_CALLS = 1 << 3;
    536         /** Calls from repeat callers are prioritized. */
    537         public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 1 << 4;
    538 
    539         private static final int[] ALL_PRIORITY_CATEGORIES = {
    540             PRIORITY_CATEGORY_REMINDERS,
    541             PRIORITY_CATEGORY_EVENTS,
    542             PRIORITY_CATEGORY_MESSAGES,
    543             PRIORITY_CATEGORY_CALLS,
    544             PRIORITY_CATEGORY_REPEAT_CALLERS,
    545         };
    546 
    547         /** Any sender is prioritized. */
    548         public static final int PRIORITY_SENDERS_ANY = 0;
    549         /** Saved contacts are prioritized. */
    550         public static final int PRIORITY_SENDERS_CONTACTS = 1;
    551         /** Only starred contacts are prioritized. */
    552         public static final int PRIORITY_SENDERS_STARRED = 2;
    553 
    554         /** Notification categories to prioritize. Bitmask of PRIORITY_CATEGORY_* constants. */
    555         public final int priorityCategories;
    556 
    557         /** Notification senders to prioritize for calls. One of:
    558          * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
    559         public final int priorityCallSenders;
    560 
    561         /** Notification senders to prioritize for messages. One of:
    562          * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
    563         public final int priorityMessageSenders;
    564 
    565         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
    566             this.priorityCategories = priorityCategories;
    567             this.priorityCallSenders = priorityCallSenders;
    568             this.priorityMessageSenders = priorityMessageSenders;
    569         }
    570 
    571         /** @hide */
    572         public Policy(Parcel source) {
    573             this(source.readInt(), source.readInt(), source.readInt());
    574         }
    575 
    576         @Override
    577         public void writeToParcel(Parcel dest, int flags) {
    578             dest.writeInt(priorityCategories);
    579             dest.writeInt(priorityCallSenders);
    580             dest.writeInt(priorityMessageSenders);
    581         }
    582 
    583         @Override
    584         public int describeContents() {
    585             return 0;
    586         }
    587 
    588         @Override
    589         public int hashCode() {
    590             return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders);
    591         }
    592 
    593         @Override
    594         public boolean equals(Object o) {
    595             if (!(o instanceof Policy)) return false;
    596             if (o == this) return true;
    597             final Policy other = (Policy) o;
    598             return other.priorityCategories == priorityCategories
    599                     && other.priorityCallSenders == priorityCallSenders
    600                     && other.priorityMessageSenders == priorityMessageSenders;
    601         }
    602 
    603         @Override
    604         public String toString() {
    605             return "NotificationManager.Policy["
    606                     + "priorityCategories=" + priorityCategoriesToString(priorityCategories)
    607                     + ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders)
    608                     + ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders)
    609                     + "]";
    610         }
    611 
    612         public static String priorityCategoriesToString(int priorityCategories) {
    613             if (priorityCategories == 0) return "";
    614             final StringBuilder sb = new StringBuilder();
    615             for (int i = 0; i < ALL_PRIORITY_CATEGORIES.length; i++) {
    616                 final int priorityCategory = ALL_PRIORITY_CATEGORIES[i];
    617                 if ((priorityCategories & priorityCategory) != 0) {
    618                     if (sb.length() > 0) sb.append(',');
    619                     sb.append(priorityCategoryToString(priorityCategory));
    620                 }
    621                 priorityCategories &= ~priorityCategory;
    622             }
    623             if (priorityCategories != 0) {
    624                 if (sb.length() > 0) sb.append(',');
    625                 sb.append("PRIORITY_CATEGORY_UNKNOWN_").append(priorityCategories);
    626             }
    627             return sb.toString();
    628         }
    629 
    630         private static String priorityCategoryToString(int priorityCategory) {
    631             switch (priorityCategory) {
    632                 case PRIORITY_CATEGORY_REMINDERS: return "PRIORITY_CATEGORY_REMINDERS";
    633                 case PRIORITY_CATEGORY_EVENTS: return "PRIORITY_CATEGORY_EVENTS";
    634                 case PRIORITY_CATEGORY_MESSAGES: return "PRIORITY_CATEGORY_MESSAGES";
    635                 case PRIORITY_CATEGORY_CALLS: return "PRIORITY_CATEGORY_CALLS";
    636                 case PRIORITY_CATEGORY_REPEAT_CALLERS: return "PRIORITY_CATEGORY_REPEAT_CALLERS";
    637                 default: return "PRIORITY_CATEGORY_UNKNOWN_" + priorityCategory;
    638             }
    639         }
    640 
    641         public static String prioritySendersToString(int prioritySenders) {
    642             switch (prioritySenders) {
    643                 case PRIORITY_SENDERS_ANY: return "PRIORITY_SENDERS_ANY";
    644                 case PRIORITY_SENDERS_CONTACTS: return "PRIORITY_SENDERS_CONTACTS";
    645                 case PRIORITY_SENDERS_STARRED: return "PRIORITY_SENDERS_STARRED";
    646                 default: return "PRIORITY_SENDERS_UNKNOWN_" + prioritySenders;
    647             }
    648         }
    649 
    650         public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
    651             @Override
    652             public Policy createFromParcel(Parcel in) {
    653                 return new Policy(in);
    654             }
    655 
    656             @Override
    657             public Policy[] newArray(int size) {
    658                 return new Policy[size];
    659             }
    660         };
    661 
    662     }
    663 
    664     /**
    665      * Recover a list of active notifications: ones that have been posted by the calling app that
    666      * have not yet been dismissed by the user or {@link #cancel(String, int)}ed by the app.
    667      *
    668      * Each notification is embedded in a {@link StatusBarNotification} object, including the
    669      * original <code>tag</code> and <code>id</code> supplied to
    670      * {@link #notify(String, int, Notification) notify()}
    671      * (via {@link StatusBarNotification#getTag() getTag()} and
    672      * {@link StatusBarNotification#getId() getId()}) as well as a copy of the original
    673      * {@link Notification} object (via {@link StatusBarNotification#getNotification()}).
    674      *
    675      * @return An array of {@link StatusBarNotification}.
    676      */
    677     public StatusBarNotification[] getActiveNotifications() {
    678         final INotificationManager service = getService();
    679         final String pkg = mContext.getPackageName();
    680         try {
    681             final ParceledListSlice<StatusBarNotification> parceledList
    682                     = service.getAppActiveNotifications(pkg, UserHandle.myUserId());
    683             final List<StatusBarNotification> list = parceledList.getList();
    684             return list.toArray(new StatusBarNotification[list.size()]);
    685         } catch (RemoteException e) {
    686             Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
    687         }
    688         return new StatusBarNotification[0];
    689     }
    690 
    691     /**
    692      * Gets the current notification interruption filter.
    693      *
    694      * <p>
    695      * The interruption filter defines which notifications are allowed to interrupt the user
    696      * (e.g. via sound &amp; vibration) and is applied globally.
    697      * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
    698      * unavailable.
    699      *
    700      * <p>
    701      * Only available if policy access is granted to this package.
    702      * See {@link #isNotificationPolicyAccessGranted}.
    703      */
    704     public final int getCurrentInterruptionFilter() {
    705         final INotificationManager service = getService();
    706         try {
    707             return zenModeToInterruptionFilter(service.getZenMode());
    708         } catch (RemoteException e) {
    709             Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
    710         }
    711         return INTERRUPTION_FILTER_UNKNOWN;
    712     }
    713 
    714     /**
    715      * Sets the current notification interruption filter.
    716      *
    717      * <p>
    718      * The interruption filter defines which notifications are allowed to interrupt the user
    719      * (e.g. via sound &amp; vibration) and is applied globally.
    720      * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
    721      * unavailable.
    722      *
    723      * <p>
    724      * Only available if policy access is granted to this package.
    725      * See {@link #isNotificationPolicyAccessGranted}.
    726      */
    727     public final void setInterruptionFilter(int interruptionFilter) {
    728         final INotificationManager service = getService();
    729         try {
    730             service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
    731         } catch (RemoteException e) {
    732             Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
    733         }
    734     }
    735 
    736     /** @hide */
    737     public static int zenModeToInterruptionFilter(int zen) {
    738         switch (zen) {
    739             case Global.ZEN_MODE_OFF: return INTERRUPTION_FILTER_ALL;
    740             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return INTERRUPTION_FILTER_PRIORITY;
    741             case Global.ZEN_MODE_ALARMS: return INTERRUPTION_FILTER_ALARMS;
    742             case Global.ZEN_MODE_NO_INTERRUPTIONS: return INTERRUPTION_FILTER_NONE;
    743             default: return INTERRUPTION_FILTER_UNKNOWN;
    744         }
    745     }
    746 
    747     /** @hide */
    748     public static int zenModeFromInterruptionFilter(int interruptionFilter, int defValue) {
    749         switch (interruptionFilter) {
    750             case INTERRUPTION_FILTER_ALL: return Global.ZEN_MODE_OFF;
    751             case INTERRUPTION_FILTER_PRIORITY: return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
    752             case INTERRUPTION_FILTER_ALARMS: return Global.ZEN_MODE_ALARMS;
    753             case INTERRUPTION_FILTER_NONE:  return Global.ZEN_MODE_NO_INTERRUPTIONS;
    754             default: return defValue;
    755         }
    756     }
    757 }
    758