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