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 & 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 & 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