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.IntDef;
     20 import android.annotation.NonNull;
     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.NotificationListenerService.Ranking;
     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.lang.annotation.Retention;
     46 import java.lang.annotation.RetentionPolicy;
     47 import java.util.HashMap;
     48 import java.util.List;
     49 import java.util.Map;
     50 import java.util.Objects;
     51 
     52 /**
     53  * Class to notify the user of events that happen.  This is how you tell
     54  * the user that something has happened in the background. {@more}
     55  *
     56  * Notifications can take different forms:
     57  * <ul>
     58  *      <li>A persistent icon that goes in the status bar and is accessible
     59  *          through the launcher, (when the user selects it, a designated Intent
     60  *          can be launched),</li>
     61  *      <li>Turning on or flashing LEDs on the device, or</li>
     62  *      <li>Alerting the user by flashing the backlight, playing a sound,
     63  *          or vibrating.</li>
     64  * </ul>
     65  *
     66  * <p>
     67  * Each of the notify methods takes an int id parameter and optionally a
     68  * {@link String} tag parameter, which may be {@code null}.  These parameters
     69  * are used to form a pair (tag, id), or ({@code null}, id) if tag is
     70  * unspecified.  This pair identifies this notification from your app to the
     71  * system, so that pair should be unique within your app.  If you call one
     72  * of the notify methods with a (tag, id) pair that is currently active and
     73  * a new set of notification parameters, it will be updated.  For example,
     74  * if you pass a new status bar icon, the old icon in the status bar will
     75  * be replaced with the new one.  This is also the same tag and id you pass
     76  * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
     77  * this notification.
     78  *
     79  * <p>
     80  * You do not instantiate this class directly; instead, retrieve it through
     81  * {@link android.content.Context#getSystemService}.
     82  *
     83  * <div class="special reference">
     84  * <h3>Developer Guides</h3>
     85  * <p>For a guide to creating notifications, read the
     86  * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
     87  * developer guide.</p>
     88  * </div>
     89  *
     90  * @see android.app.Notification
     91  * @see android.content.Context#getSystemService
     92  */
     93 public class NotificationManager
     94 {
     95     private static String TAG = "NotificationManager";
     96     private static boolean localLOGV = false;
     97 
     98     /**
     99      * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
    100      * This broadcast is only sent to registered receivers.
    101      *
    102      * @hide
    103      */
    104     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    105     public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED
    106             = "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED";
    107 
    108     /**
    109      * Intent that is broadcast when the state of {@link #isNotificationPolicyAccessGranted()}
    110      * changes.
    111      *
    112      * This broadcast is only sent to registered receivers, and only to the apps that have changed.
    113      */
    114     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    115     public static final String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED
    116             = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
    117 
    118     /**
    119      * Intent that is broadcast when the state of getNotificationPolicy() changes.
    120      * This broadcast is only sent to registered receivers.
    121      */
    122     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    123     public static final String ACTION_NOTIFICATION_POLICY_CHANGED
    124             = "android.app.action.NOTIFICATION_POLICY_CHANGED";
    125 
    126     /**
    127      * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
    128      * This broadcast is only sent to registered receivers.
    129      */
    130     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    131     public static final String ACTION_INTERRUPTION_FILTER_CHANGED
    132             = "android.app.action.INTERRUPTION_FILTER_CHANGED";
    133 
    134     /**
    135      * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
    136      * @hide
    137      */
    138     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
    139     public static final String ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL
    140             = "android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL";
    141 
    142     /** @hide */
    143     @IntDef({INTERRUPTION_FILTER_NONE, INTERRUPTION_FILTER_PRIORITY, INTERRUPTION_FILTER_ALARMS,
    144             INTERRUPTION_FILTER_ALL, INTERRUPTION_FILTER_UNKNOWN})
    145     @Retention(RetentionPolicy.SOURCE)
    146     public @interface InterruptionFilter {}
    147 
    148     /**
    149      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    150      *     Normal interruption filter - no notifications are suppressed.
    151      */
    152     public static final int INTERRUPTION_FILTER_ALL = 1;
    153 
    154     /**
    155      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    156      *     Priority interruption filter - all notifications are suppressed except those that match
    157      *     the priority criteria. Some audio streams are muted. See
    158      *     {@link Policy#priorityCallSenders}, {@link Policy#priorityCategories},
    159      *     {@link Policy#priorityMessageSenders} to define or query this criteria. Users can
    160      *     additionally specify packages that can bypass this interruption filter.
    161      */
    162     public static final int INTERRUPTION_FILTER_PRIORITY = 2;
    163 
    164     /**
    165      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    166      *     No interruptions filter - all notifications are suppressed and all audio streams (except
    167      *     those used for phone calls) and vibrations are muted.
    168      */
    169     public static final int INTERRUPTION_FILTER_NONE = 3;
    170 
    171     /**
    172      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
    173      *     Alarms only interruption filter - all notifications except those of category
    174      *     {@link Notification#CATEGORY_ALARM} are suppressed. Some audio streams are muted.
    175      */
    176     public static final int INTERRUPTION_FILTER_ALARMS = 4;
    177 
    178     /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when
    179      * the value is unavailable for any reason.
    180      */
    181     public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
    182 
    183     /** @hide */
    184     @IntDef({VISIBILITY_NO_OVERRIDE, IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
    185             IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH,
    186             IMPORTANCE_MAX})
    187     @Retention(RetentionPolicy.SOURCE)
    188     public @interface Importance {}
    189 
    190     /** Value signifying that the user has not expressed a per-app visibility override value.
    191      * @hide */
    192     public static final int VISIBILITY_NO_OVERRIDE = -1000;
    193     /**
    194      * Value signifying that the user has not expressed an importance.
    195      *
    196      * This value is for persisting preferences, and should never be associated with
    197      * an actual notification.
    198      */
    199     public static final int IMPORTANCE_UNSPECIFIED = -1000;
    200 
    201     /**
    202      * A notification with no importance: shows nowhere, is blocked.
    203      */
    204     public static final int IMPORTANCE_NONE = 0;
    205 
    206     /**
    207      * Min notification importance: only shows in the shade, below the fold.
    208      */
    209     public static final int IMPORTANCE_MIN = 1;
    210 
    211     /**
    212      * Low notification importance: shows everywhere, but is not intrusive.
    213      */
    214     public static final int IMPORTANCE_LOW = 2;
    215 
    216     /**
    217      * Default notification importance: shows everywhere, allowed to makes noise,
    218      * but does not visually intrude.
    219      */
    220     public static final int IMPORTANCE_DEFAULT = 3;
    221 
    222     /**
    223      * Higher notification importance: shows everywhere, allowed to makes noise and peek.
    224      */
    225     public static final int IMPORTANCE_HIGH = 4;
    226 
    227     /**
    228      * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
    229      * use full screen intents.
    230      */
    231     public static final int IMPORTANCE_MAX = 5;
    232 
    233     private static INotificationManager sService;
    234 
    235     /** @hide */
    236     static public INotificationManager getService()
    237     {
    238         if (sService != null) {
    239             return sService;
    240         }
    241         IBinder b = ServiceManager.getService("notification");
    242         sService = INotificationManager.Stub.asInterface(b);
    243         return sService;
    244     }
    245 
    246     /*package*/ NotificationManager(Context context, Handler handler)
    247     {
    248         mContext = context;
    249     }
    250 
    251     /** {@hide} */
    252     public static NotificationManager from(Context context) {
    253         return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    254     }
    255 
    256     /**
    257      * Post a notification to be shown in the status bar. If a notification with
    258      * the same id has already been posted by your application and has not yet been canceled, it
    259      * will be replaced by the updated information.
    260      *
    261      * @param id An identifier for this notification unique within your
    262      *        application.
    263      * @param notification A {@link Notification} object describing what to show the user. Must not
    264      *        be null.
    265      */
    266     public void notify(int id, Notification notification)
    267     {
    268         notify(null, id, notification);
    269     }
    270 
    271     /**
    272      * Post a notification to be shown in the status bar. If a notification with
    273      * the same tag and id has already been posted by your application and has not yet been
    274      * canceled, it will be replaced by the updated information.
    275      *
    276      * @param tag A string identifier for this notification.  May be {@code null}.
    277      * @param id An identifier for this notification.  The pair (tag, id) must be unique
    278      *        within your application.
    279      * @param notification A {@link Notification} object describing what to
    280      *        show the user. Must not be null.
    281      */
    282     public void notify(String tag, int id, Notification notification)
    283     {
    284         notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId()));
    285     }
    286 
    287     /**
    288      * @hide
    289      */
    290     public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
    291     {
    292         int[] idOut = new int[1];
    293         INotificationManager service = getService();
    294         String pkg = mContext.getPackageName();
    295         // Fix the notification as best we can.
    296         Notification.addFieldsFromContext(mContext, notification);
    297         if (notification.sound != null) {
    298             notification.sound = notification.sound.getCanonicalUri();
    299             if (StrictMode.vmFileUriExposureEnabled()) {
    300                 notification.sound.checkFileUriExposed("Notification.sound");
    301             }
    302         }
    303         fixLegacySmallIcon(notification, pkg);
    304         if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
    305             if (notification.getSmallIcon() == null) {
    306                 throw new IllegalArgumentException("Invalid notification (no valid small icon): "
    307                         + notification);
    308             }
    309         }
    310         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
    311         final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
    312         try {
    313             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
    314                     copy, idOut, user.getIdentifier());
    315             if (id != idOut[0]) {
    316                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
    317             }
    318         } catch (RemoteException e) {
    319             throw e.rethrowFromSystemServer();
    320         }
    321     }
    322 
    323     private void fixLegacySmallIcon(Notification n, String pkg) {
    324         if (n.getSmallIcon() == null && n.icon != 0) {
    325             n.setSmallIcon(Icon.createWithResource(pkg, n.icon));
    326         }
    327     }
    328 
    329     /**
    330      * Cancel a previously shown notification.  If it's transient, the view
    331      * will be hidden.  If it's persistent, it will be removed from the status
    332      * bar.
    333      */
    334     public void cancel(int id)
    335     {
    336         cancel(null, id);
    337     }
    338 
    339     /**
    340      * Cancel a previously shown notification.  If it's transient, the view
    341      * will be hidden.  If it's persistent, it will be removed from the status
    342      * bar.
    343      */
    344     public void cancel(String tag, int id)
    345     {
    346         cancelAsUser(tag, id, new UserHandle(UserHandle.myUserId()));
    347     }
    348 
    349     /**
    350      * @hide
    351      */
    352     public void cancelAsUser(String tag, int id, UserHandle user)
    353     {
    354         INotificationManager service = getService();
    355         String pkg = mContext.getPackageName();
    356         if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
    357         try {
    358             service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
    359         } catch (RemoteException e) {
    360             throw e.rethrowFromSystemServer();
    361         }
    362     }
    363 
    364     /**
    365      * Cancel all previously shown notifications. See {@link #cancel} for the
    366      * detailed behavior.
    367      */
    368     public void cancelAll()
    369     {
    370         INotificationManager service = getService();
    371         String pkg = mContext.getPackageName();
    372         if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
    373         try {
    374             service.cancelAllNotifications(pkg, UserHandle.myUserId());
    375         } catch (RemoteException e) {
    376             throw e.rethrowFromSystemServer();
    377         }
    378     }
    379 
    380     /**
    381      * @hide
    382      */
    383     public ComponentName getEffectsSuppressor() {
    384         INotificationManager service = getService();
    385         try {
    386             return service.getEffectsSuppressor();
    387         } catch (RemoteException e) {
    388             throw e.rethrowFromSystemServer();
    389         }
    390     }
    391 
    392     /**
    393      * @hide
    394      */
    395     public boolean matchesCallFilter(Bundle extras) {
    396         INotificationManager service = getService();
    397         try {
    398             return service.matchesCallFilter(extras);
    399         } catch (RemoteException e) {
    400             throw e.rethrowFromSystemServer();
    401         }
    402     }
    403 
    404     /**
    405      * @hide
    406      */
    407     public boolean isSystemConditionProviderEnabled(String path) {
    408         INotificationManager service = getService();
    409         try {
    410             return service.isSystemConditionProviderEnabled(path);
    411         } catch (RemoteException e) {
    412             throw e.rethrowFromSystemServer();
    413         }
    414     }
    415 
    416     /**
    417      * @hide
    418      */
    419     public void setZenMode(int mode, Uri conditionId, String reason) {
    420         INotificationManager service = getService();
    421         try {
    422             service.setZenMode(mode, conditionId, reason);
    423         } catch (RemoteException e) {
    424             throw e.rethrowFromSystemServer();
    425         }
    426     }
    427 
    428     /**
    429      * @hide
    430      */
    431     public int getZenMode() {
    432         INotificationManager service = getService();
    433         try {
    434             return service.getZenMode();
    435         } catch (RemoteException e) {
    436             throw e.rethrowFromSystemServer();
    437         }
    438     }
    439 
    440     /**
    441      * @hide
    442      */
    443     public ZenModeConfig getZenModeConfig() {
    444         INotificationManager service = getService();
    445         try {
    446             return service.getZenModeConfig();
    447         } catch (RemoteException e) {
    448             throw e.rethrowFromSystemServer();
    449         }
    450     }
    451 
    452     /**
    453      * @hide
    454      */
    455     public int getRuleInstanceCount(ComponentName owner) {
    456         INotificationManager service = getService();
    457         try {
    458             return service.getRuleInstanceCount(owner);
    459         } catch (RemoteException e) {
    460             throw e.rethrowFromSystemServer();
    461         }
    462     }
    463 
    464     /**
    465      * Returns AutomaticZenRules owned by the caller.
    466      *
    467      * <p>
    468      * Throws a SecurityException if policy access is granted to this package.
    469      * See {@link #isNotificationPolicyAccessGranted}.
    470      */
    471     public Map<String, AutomaticZenRule> getAutomaticZenRules() {
    472         INotificationManager service = getService();
    473         try {
    474             List<ZenModeConfig.ZenRule> rules = service.getZenRules();
    475             Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
    476             for (ZenModeConfig.ZenRule rule : rules) {
    477                 ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
    478                         rule.conditionId, zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
    479                         rule.creationTime));
    480             }
    481             return ruleMap;
    482         } catch (RemoteException e) {
    483             throw e.rethrowFromSystemServer();
    484         }
    485     }
    486 
    487     /**
    488      * Returns the AutomaticZenRule with the given id, if it exists and the caller has access.
    489      *
    490      * <p>
    491      * Throws a SecurityException if policy access is granted to this package.
    492      * See {@link #isNotificationPolicyAccessGranted}.
    493      *
    494      * <p>
    495      * Returns null if there are no zen rules that match the given id, or if the calling package
    496      * doesn't own the matching rule. See {@link AutomaticZenRule#getOwner}.
    497      */
    498     public AutomaticZenRule getAutomaticZenRule(String id) {
    499         INotificationManager service = getService();
    500         try {
    501             return service.getAutomaticZenRule(id);
    502         } catch (RemoteException e) {
    503             throw e.rethrowFromSystemServer();
    504         }
    505     }
    506 
    507     /**
    508      * Creates the given zen rule.
    509      *
    510      * <p>
    511      * Throws a SecurityException if policy access is granted to this package.
    512      * See {@link #isNotificationPolicyAccessGranted}.
    513      *
    514      * @param automaticZenRule the rule to create.
    515      * @return The id of the newly created rule; null if the rule could not be created.
    516      */
    517     public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
    518         INotificationManager service = getService();
    519         try {
    520             return service.addAutomaticZenRule(automaticZenRule);
    521         } catch (RemoteException e) {
    522             throw e.rethrowFromSystemServer();
    523         }
    524     }
    525 
    526     /**
    527      * Updates the given zen rule.
    528      *
    529      * <p>
    530      * Throws a SecurityException if policy access is granted to this package.
    531      * See {@link #isNotificationPolicyAccessGranted}.
    532      *
    533      * <p>
    534      * Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}.
    535      * @param id The id of the rule to update
    536      * @param automaticZenRule the rule to update.
    537      * @return Whether the rule was successfully updated.
    538      */
    539     public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
    540         INotificationManager service = getService();
    541         try {
    542             return service.updateAutomaticZenRule(id, automaticZenRule);
    543         } catch (RemoteException e) {
    544             throw e.rethrowFromSystemServer();
    545         }
    546     }
    547 
    548     /**
    549      * Deletes the automatic zen rule with the given id.
    550      *
    551      * <p>
    552      * Throws a SecurityException if policy access is granted to this package.
    553      * See {@link #isNotificationPolicyAccessGranted}.
    554      *
    555      * <p>
    556      * Callers can only delete rules that they own. See {@link AutomaticZenRule#getOwner}.
    557      * @param id the id of the rule to delete.
    558      * @return Whether the rule was successfully deleted.
    559      */
    560     public boolean removeAutomaticZenRule(String id) {
    561         INotificationManager service = getService();
    562         try {
    563             return service.removeAutomaticZenRule(id);
    564         } catch (RemoteException e) {
    565             throw e.rethrowFromSystemServer();
    566         }
    567     }
    568 
    569     /**
    570      * Deletes all automatic zen rules owned by the given package.
    571      *
    572      * @hide
    573      */
    574     public boolean removeAutomaticZenRules(String packageName) {
    575         INotificationManager service = getService();
    576         try {
    577             return service.removeAutomaticZenRules(packageName);
    578         } catch (RemoteException e) {
    579             throw e.rethrowFromSystemServer();
    580         }
    581     }
    582 
    583     /**
    584      * Returns the user specified importance for notifications from the calling package.
    585      *
    586      * @return An importance level, such as {@link #IMPORTANCE_DEFAULT}.
    587      */
    588     public @Importance int getImportance() {
    589         INotificationManager service = getService();
    590         try {
    591             return service.getPackageImportance(mContext.getPackageName());
    592         } catch (RemoteException e) {
    593             throw e.rethrowFromSystemServer();
    594         }
    595     }
    596 
    597     /**
    598      * Returns whether notifications from the calling package are blocked.
    599      */
    600     public boolean areNotificationsEnabled() {
    601         INotificationManager service = getService();
    602         try {
    603             return service.areNotificationsEnabled(mContext.getPackageName());
    604         } catch (RemoteException e) {
    605             throw e.rethrowFromSystemServer();
    606         }
    607     }
    608 
    609     /**
    610      * Checks the ability to read/modify notification policy for the calling package.
    611      *
    612      * <p>
    613      * Returns true if the calling package can read/modify notification policy.
    614      *
    615      * <p>
    616      * Request policy access by sending the user to the activity that matches the system intent
    617      * action {@link android.provider.Settings#ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS}.
    618      *
    619      * <p>
    620      * Use {@link #ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED} to listen for
    621      * user grant or denial of this access.
    622      */
    623     public boolean isNotificationPolicyAccessGranted() {
    624         INotificationManager service = getService();
    625         try {
    626             return service.isNotificationPolicyAccessGranted(mContext.getOpPackageName());
    627         } catch (RemoteException e) {
    628             throw e.rethrowFromSystemServer();
    629         }
    630     }
    631 
    632     /** @hide */
    633     public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
    634         INotificationManager service = getService();
    635         try {
    636             return service.isNotificationPolicyAccessGrantedForPackage(pkg);
    637         } catch (RemoteException e) {
    638             throw e.rethrowFromSystemServer();
    639         }
    640     }
    641 
    642     /**
    643      * Gets the current notification policy.
    644      *
    645      * <p>
    646      * Only available if policy access is granted to this package.
    647      * See {@link #isNotificationPolicyAccessGranted}.
    648      */
    649     public Policy getNotificationPolicy() {
    650         INotificationManager service = getService();
    651         try {
    652             return service.getNotificationPolicy(mContext.getOpPackageName());
    653         } catch (RemoteException e) {
    654             throw e.rethrowFromSystemServer();
    655         }
    656     }
    657 
    658     /**
    659      * Sets the current notification policy.
    660      *
    661      * <p>
    662      * Only available if policy access is granted to this package.
    663      * See {@link #isNotificationPolicyAccessGranted}.
    664      *
    665      * @param policy The new desired policy.
    666      */
    667     public void setNotificationPolicy(@NonNull Policy policy) {
    668         checkRequired("policy", policy);
    669         INotificationManager service = getService();
    670         try {
    671             service.setNotificationPolicy(mContext.getOpPackageName(), policy);
    672         } catch (RemoteException e) {
    673             throw e.rethrowFromSystemServer();
    674         }
    675     }
    676 
    677     /** @hide */
    678     public void setNotificationPolicyAccessGranted(String pkg, boolean granted) {
    679         INotificationManager service = getService();
    680         try {
    681             service.setNotificationPolicyAccessGranted(pkg, granted);
    682         } catch (RemoteException e) {
    683             throw e.rethrowFromSystemServer();
    684         }
    685     }
    686 
    687     /** @hide */
    688     public ArraySet<String> getPackagesRequestingNotificationPolicyAccess() {
    689         INotificationManager service = getService();
    690         try {
    691             final String[] pkgs = service.getPackagesRequestingNotificationPolicyAccess();
    692             if (pkgs != null && pkgs.length > 0) {
    693                 final ArraySet<String> rt = new ArraySet<>(pkgs.length);
    694                 for (int i = 0; i < pkgs.length; i++) {
    695                     rt.add(pkgs[i]);
    696                 }
    697                 return rt;
    698             }
    699         } catch (RemoteException e) {
    700             throw e.rethrowFromSystemServer();
    701         }
    702         return new ArraySet<>();
    703     }
    704 
    705     private Context mContext;
    706 
    707     private static void checkRequired(String name, Object value) {
    708         if (value == null) {
    709             throw new IllegalArgumentException(name + " is required");
    710         }
    711     }
    712 
    713     /**
    714      * Notification policy configuration.  Represents user-preferences for notification
    715      * filtering.
    716      */
    717     public static class Policy implements android.os.Parcelable {
    718         /** Reminder notifications are prioritized. */
    719         public static final int PRIORITY_CATEGORY_REMINDERS = 1 << 0;
    720         /** Event notifications are prioritized. */
    721         public static final int PRIORITY_CATEGORY_EVENTS = 1 << 1;
    722         /** Message notifications are prioritized. */
    723         public static final int PRIORITY_CATEGORY_MESSAGES = 1 << 2;
    724         /** Calls are prioritized. */
    725         public static final int PRIORITY_CATEGORY_CALLS = 1 << 3;
    726         /** Calls from repeat callers are prioritized. */
    727         public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 1 << 4;
    728 
    729         private static final int[] ALL_PRIORITY_CATEGORIES = {
    730             PRIORITY_CATEGORY_REMINDERS,
    731             PRIORITY_CATEGORY_EVENTS,
    732             PRIORITY_CATEGORY_MESSAGES,
    733             PRIORITY_CATEGORY_CALLS,
    734             PRIORITY_CATEGORY_REPEAT_CALLERS,
    735         };
    736 
    737         /** Any sender is prioritized. */
    738         public static final int PRIORITY_SENDERS_ANY = 0;
    739         /** Saved contacts are prioritized. */
    740         public static final int PRIORITY_SENDERS_CONTACTS = 1;
    741         /** Only starred contacts are prioritized. */
    742         public static final int PRIORITY_SENDERS_STARRED = 2;
    743 
    744         /** Notification categories to prioritize. Bitmask of PRIORITY_CATEGORY_* constants. */
    745         public final int priorityCategories;
    746 
    747         /** Notification senders to prioritize for calls. One of:
    748          * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
    749         public final int priorityCallSenders;
    750 
    751         /** Notification senders to prioritize for messages. One of:
    752          * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
    753         public final int priorityMessageSenders;
    754 
    755         /**
    756          * @hide
    757          */
    758         public static final int SUPPRESSED_EFFECTS_UNSET = -1;
    759         /**
    760          * Whether notifications suppressed by DND should not interrupt visually (e.g. with
    761          * notification lights or by turning the screen on) when the screen is off.
    762          */
    763         public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0;
    764         /**
    765          * Whether notifications suppressed by DND should not interrupt visually when the screen
    766          * is on (e.g. by peeking onto the screen).
    767          */
    768         public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1;
    769 
    770         private static final int[] ALL_SUPPRESSED_EFFECTS = {
    771                 SUPPRESSED_EFFECT_SCREEN_OFF,
    772                 SUPPRESSED_EFFECT_SCREEN_ON,
    773         };
    774 
    775         /**
    776          * Visual effects to suppress for a notification that is filtered by Do Not Disturb mode.
    777          * Bitmask of SUPPRESSED_EFFECT_* constants.
    778          */
    779         public final int suppressedVisualEffects;
    780 
    781         /**
    782          * Constructs a policy for Do Not Disturb priority mode behavior.
    783          *
    784          * @param priorityCategories bitmask of categories of notifications that can bypass DND.
    785          * @param priorityCallSenders which callers can bypass DND.
    786          * @param priorityMessageSenders which message senders can bypass DND.
    787          */
    788         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
    789             this(priorityCategories, priorityCallSenders, priorityMessageSenders,
    790                     SUPPRESSED_EFFECTS_UNSET);
    791         }
    792 
    793         /**
    794          * Constructs a policy for Do Not Disturb priority mode behavior.
    795          *
    796          * @param priorityCategories bitmask of categories of notifications that can bypass DND.
    797          * @param priorityCallSenders which callers can bypass DND.
    798          * @param priorityMessageSenders which message senders can bypass DND.
    799          * @param suppressedVisualEffects which visual interruptions should be suppressed from
    800          *                                notifications that are filtered by DND.
    801          */
    802         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders,
    803                 int suppressedVisualEffects) {
    804             this.priorityCategories = priorityCategories;
    805             this.priorityCallSenders = priorityCallSenders;
    806             this.priorityMessageSenders = priorityMessageSenders;
    807             this.suppressedVisualEffects = suppressedVisualEffects;
    808         }
    809 
    810         /** @hide */
    811         public Policy(Parcel source) {
    812             this(source.readInt(), source.readInt(), source.readInt(), source.readInt());
    813         }
    814 
    815         @Override
    816         public void writeToParcel(Parcel dest, int flags) {
    817             dest.writeInt(priorityCategories);
    818             dest.writeInt(priorityCallSenders);
    819             dest.writeInt(priorityMessageSenders);
    820             dest.writeInt(suppressedVisualEffects);
    821         }
    822 
    823         @Override
    824         public int describeContents() {
    825             return 0;
    826         }
    827 
    828         @Override
    829         public int hashCode() {
    830             return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders,
    831                     suppressedVisualEffects);
    832         }
    833 
    834         @Override
    835         public boolean equals(Object o) {
    836             if (!(o instanceof Policy)) return false;
    837             if (o == this) return true;
    838             final Policy other = (Policy) o;
    839             return other.priorityCategories == priorityCategories
    840                     && other.priorityCallSenders == priorityCallSenders
    841                     && other.priorityMessageSenders == priorityMessageSenders
    842                     && other.suppressedVisualEffects == suppressedVisualEffects;
    843         }
    844 
    845         @Override
    846         public String toString() {
    847             return "NotificationManager.Policy["
    848                     + "priorityCategories=" + priorityCategoriesToString(priorityCategories)
    849                     + ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders)
    850                     + ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders)
    851                     + ",suppressedVisualEffects="
    852                     + suppressedEffectsToString(suppressedVisualEffects)
    853                     + "]";
    854         }
    855 
    856         public static String suppressedEffectsToString(int effects) {
    857             if (effects <= 0) return "";
    858             final StringBuilder sb = new StringBuilder();
    859             for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) {
    860                 final int effect = ALL_SUPPRESSED_EFFECTS[i];
    861                 if ((effects & effect) != 0) {
    862                     if (sb.length() > 0) sb.append(',');
    863                     sb.append(effectToString(effect));
    864                 }
    865                 effects &= ~effect;
    866             }
    867             if (effects != 0) {
    868                 if (sb.length() > 0) sb.append(',');
    869                 sb.append("UNKNOWN_").append(effects);
    870             }
    871             return sb.toString();
    872         }
    873 
    874         public static String priorityCategoriesToString(int priorityCategories) {
    875             if (priorityCategories == 0) return "";
    876             final StringBuilder sb = new StringBuilder();
    877             for (int i = 0; i < ALL_PRIORITY_CATEGORIES.length; i++) {
    878                 final int priorityCategory = ALL_PRIORITY_CATEGORIES[i];
    879                 if ((priorityCategories & priorityCategory) != 0) {
    880                     if (sb.length() > 0) sb.append(',');
    881                     sb.append(priorityCategoryToString(priorityCategory));
    882                 }
    883                 priorityCategories &= ~priorityCategory;
    884             }
    885             if (priorityCategories != 0) {
    886                 if (sb.length() > 0) sb.append(',');
    887                 sb.append("PRIORITY_CATEGORY_UNKNOWN_").append(priorityCategories);
    888             }
    889             return sb.toString();
    890         }
    891 
    892         private static String effectToString(int effect) {
    893             switch (effect) {
    894                 case SUPPRESSED_EFFECT_SCREEN_OFF: return "SUPPRESSED_EFFECT_SCREEN_OFF";
    895                 case SUPPRESSED_EFFECT_SCREEN_ON: return "SUPPRESSED_EFFECT_SCREEN_ON";
    896                 case SUPPRESSED_EFFECTS_UNSET: return "SUPPRESSED_EFFECTS_UNSET";
    897                 default: return "UNKNOWN_" + effect;
    898             }
    899         }
    900 
    901         private static String priorityCategoryToString(int priorityCategory) {
    902             switch (priorityCategory) {
    903                 case PRIORITY_CATEGORY_REMINDERS: return "PRIORITY_CATEGORY_REMINDERS";
    904                 case PRIORITY_CATEGORY_EVENTS: return "PRIORITY_CATEGORY_EVENTS";
    905                 case PRIORITY_CATEGORY_MESSAGES: return "PRIORITY_CATEGORY_MESSAGES";
    906                 case PRIORITY_CATEGORY_CALLS: return "PRIORITY_CATEGORY_CALLS";
    907                 case PRIORITY_CATEGORY_REPEAT_CALLERS: return "PRIORITY_CATEGORY_REPEAT_CALLERS";
    908                 default: return "PRIORITY_CATEGORY_UNKNOWN_" + priorityCategory;
    909             }
    910         }
    911 
    912         public static String prioritySendersToString(int prioritySenders) {
    913             switch (prioritySenders) {
    914                 case PRIORITY_SENDERS_ANY: return "PRIORITY_SENDERS_ANY";
    915                 case PRIORITY_SENDERS_CONTACTS: return "PRIORITY_SENDERS_CONTACTS";
    916                 case PRIORITY_SENDERS_STARRED: return "PRIORITY_SENDERS_STARRED";
    917                 default: return "PRIORITY_SENDERS_UNKNOWN_" + prioritySenders;
    918             }
    919         }
    920 
    921         public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
    922             @Override
    923             public Policy createFromParcel(Parcel in) {
    924                 return new Policy(in);
    925             }
    926 
    927             @Override
    928             public Policy[] newArray(int size) {
    929                 return new Policy[size];
    930             }
    931         };
    932     }
    933 
    934     /**
    935      * Recover a list of active notifications: ones that have been posted by the calling app that
    936      * have not yet been dismissed by the user or {@link #cancel(String, int)}ed by the app.
    937      *
    938      * Each notification is embedded in a {@link StatusBarNotification} object, including the
    939      * original <code>tag</code> and <code>id</code> supplied to
    940      * {@link #notify(String, int, Notification) notify()}
    941      * (via {@link StatusBarNotification#getTag() getTag()} and
    942      * {@link StatusBarNotification#getId() getId()}) as well as a copy of the original
    943      * {@link Notification} object (via {@link StatusBarNotification#getNotification()}).
    944      *
    945      * @return An array of {@link StatusBarNotification}.
    946      */
    947     public StatusBarNotification[] getActiveNotifications() {
    948         final INotificationManager service = getService();
    949         final String pkg = mContext.getPackageName();
    950         try {
    951             final ParceledListSlice<StatusBarNotification> parceledList
    952                     = service.getAppActiveNotifications(pkg, UserHandle.myUserId());
    953             final List<StatusBarNotification> list = parceledList.getList();
    954             return list.toArray(new StatusBarNotification[list.size()]);
    955         } catch (RemoteException e) {
    956             throw e.rethrowFromSystemServer();
    957         }
    958     }
    959 
    960     /**
    961      * Gets the current notification interruption filter.
    962      *
    963      * <p>
    964      * The interruption filter defines which notifications are allowed to interrupt the user
    965      * (e.g. via sound &amp; vibration) and is applied globally.
    966      * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
    967      * unavailable.
    968      */
    969     public final @InterruptionFilter int getCurrentInterruptionFilter() {
    970         final INotificationManager service = getService();
    971         try {
    972             return zenModeToInterruptionFilter(service.getZenMode());
    973         } catch (RemoteException e) {
    974             throw e.rethrowFromSystemServer();
    975         }
    976     }
    977 
    978     /**
    979      * Sets the current notification interruption filter.
    980      *
    981      * <p>
    982      * The interruption filter defines which notifications are allowed to interrupt the user
    983      * (e.g. via sound &amp; vibration) and is applied globally.
    984      * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
    985      * unavailable.
    986      *
    987      * <p>
    988      * Only available if policy access is granted to this package.
    989      * See {@link #isNotificationPolicyAccessGranted}.
    990      */
    991     public final void setInterruptionFilter(int interruptionFilter) {
    992         final INotificationManager service = getService();
    993         try {
    994             service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
    995         } catch (RemoteException e) {
    996             throw e.rethrowFromSystemServer();
    997         }
    998     }
    999 
   1000     /** @hide */
   1001     public static int zenModeToInterruptionFilter(int zen) {
   1002         switch (zen) {
   1003             case Global.ZEN_MODE_OFF: return INTERRUPTION_FILTER_ALL;
   1004             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return INTERRUPTION_FILTER_PRIORITY;
   1005             case Global.ZEN_MODE_ALARMS: return INTERRUPTION_FILTER_ALARMS;
   1006             case Global.ZEN_MODE_NO_INTERRUPTIONS: return INTERRUPTION_FILTER_NONE;
   1007             default: return INTERRUPTION_FILTER_UNKNOWN;
   1008         }
   1009     }
   1010 
   1011     /** @hide */
   1012     public static int zenModeFromInterruptionFilter(int interruptionFilter, int defValue) {
   1013         switch (interruptionFilter) {
   1014             case INTERRUPTION_FILTER_ALL: return Global.ZEN_MODE_OFF;
   1015             case INTERRUPTION_FILTER_PRIORITY: return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
   1016             case INTERRUPTION_FILTER_ALARMS: return Global.ZEN_MODE_ALARMS;
   1017             case INTERRUPTION_FILTER_NONE:  return Global.ZEN_MODE_NO_INTERRUPTIONS;
   1018             default: return defValue;
   1019         }
   1020     }
   1021 }
   1022