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