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 static android.Manifest.permission.POST_NOTIFICATIONS; 20 import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID; 21 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 22 import static android.service.notification.Flags.notificationClassification; 23 24 import android.annotation.CallbackExecutor; 25 import android.annotation.FlaggedApi; 26 import android.annotation.IntDef; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.RequiresPermission; 30 import android.annotation.SdkConstant; 31 import android.annotation.SuppressLint; 32 import android.annotation.SystemApi; 33 import android.annotation.SystemService; 34 import android.annotation.TestApi; 35 import android.annotation.UserHandleAware; 36 import android.annotation.WorkerThread; 37 import android.app.Notification.Builder; 38 import android.app.compat.CompatChanges; 39 import android.compat.annotation.ChangeId; 40 import android.compat.annotation.EnabledSince; 41 import android.compat.annotation.UnsupportedAppUsage; 42 import android.content.ComponentName; 43 import android.content.Context; 44 import android.content.Intent; 45 import android.content.pm.PackageManager; 46 import android.content.pm.ParceledListSlice; 47 import android.content.pm.ShortcutInfo; 48 import android.graphics.drawable.Icon; 49 import android.net.Uri; 50 import android.os.Binder; 51 import android.os.Build; 52 import android.os.Bundle; 53 import android.os.IBinder; 54 import android.os.IpcDataCache; 55 import android.os.Parcel; 56 import android.os.Parcelable; 57 import android.os.RemoteException; 58 import android.os.ServiceManager; 59 import android.os.StrictMode; 60 import android.os.SystemClock; 61 import android.os.UserHandle; 62 import android.provider.Settings; 63 import android.provider.Settings.Global; 64 import android.service.notification.Adjustment; 65 import android.service.notification.Condition; 66 import android.service.notification.RateEstimator; 67 import android.service.notification.StatusBarNotification; 68 import android.service.notification.ZenDeviceEffects; 69 import android.service.notification.ZenModeConfig; 70 import android.service.notification.ZenPolicy; 71 import android.text.TextUtils; 72 import android.util.ArrayMap; 73 import android.util.Log; 74 import android.util.LruCache; 75 import android.util.Slog; 76 import android.util.proto.ProtoOutputStream; 77 78 import com.android.internal.annotations.VisibleForTesting; 79 import com.android.internal.notification.NotificationChannelGroupsHelper; 80 81 import java.lang.annotation.Retention; 82 import java.lang.annotation.RetentionPolicy; 83 import java.time.Duration; 84 import java.time.Instant; 85 import java.time.InstantSource; 86 import java.util.ArrayList; 87 import java.util.Arrays; 88 import java.util.HashMap; 89 import java.util.HashSet; 90 import java.util.List; 91 import java.util.Map; 92 import java.util.Objects; 93 import java.util.Set; 94 import java.util.concurrent.Executor; 95 96 /** 97 * Class to notify the user of events that happen. This is how you tell 98 * the user that something has happened in the background. 99 * 100 * <p>Notifications can take different forms: 101 * <ul> 102 * <li>A persistent icon that goes in the status bar and is accessible 103 * through the launcher, (when the user selects it, a designated Intent 104 * can be launched),</li> 105 * <li>Turning on or flashing LEDs on the device, or</li> 106 * <li>Alerting the user by flashing the backlight, playing a sound, 107 * or vibrating.</li> 108 * </ul> 109 * 110 * <p> 111 * Each of the notify methods takes an int id parameter and optionally a 112 * {@link String} tag parameter, which may be {@code null}. These parameters 113 * are used to form a pair (tag, id), or ({@code null}, id) if tag is 114 * unspecified. This pair identifies this notification from your app to the 115 * system, so that pair should be unique within your app. If you call one 116 * of the notify methods with a (tag, id) pair that is currently active and 117 * a new set of notification parameters, it will be updated. For example, 118 * if you pass a new status bar icon, the old icon in the status bar will 119 * be replaced with the new one. This is also the same tag and id you pass 120 * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear 121 * this notification. 122 * 123 * <div class="special reference"> 124 * <h3>Developer Guides</h3> 125 * <p>For a guide to creating notifications, read the 126 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a> 127 * developer guide.</p> 128 * </div> 129 * 130 * @see android.app.Notification 131 */ 132 @SystemService(Context.NOTIFICATION_SERVICE) 133 public class NotificationManager { 134 private static String TAG = "NotificationManager"; 135 private static boolean localLOGV = false; 136 137 /** 138 * Intent that is broadcast when an application is blocked or unblocked. 139 * 140 * This broadcast is only sent to the app whose block state has changed. 141 * 142 * Input: nothing 143 * Output: {@link #EXTRA_BLOCKED_STATE} 144 */ 145 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 146 public static final String ACTION_APP_BLOCK_STATE_CHANGED = 147 "android.app.action.APP_BLOCK_STATE_CHANGED"; 148 149 /** 150 * Intent that is broadcast when a {@link NotificationChannel} is blocked 151 * (when {@link NotificationChannel#getImportance()} is {@link #IMPORTANCE_NONE}) or unblocked 152 * (when {@link NotificationChannel#getImportance()} is anything other than 153 * {@link #IMPORTANCE_NONE}). 154 * 155 * This broadcast is only sent to the app that owns the channel that has changed. 156 * 157 * Input: nothing 158 * Output: {@link #EXTRA_NOTIFICATION_CHANNEL_ID} 159 * Output: {@link #EXTRA_BLOCKED_STATE} 160 */ 161 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 162 public static final String ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED = 163 "android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED"; 164 165 /** 166 * Activity action: Toggle notification panel of the specified handler. 167 * 168 * <p><strong>Important:</strong>You must protect the activity that handles this action with 169 * the {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission to ensure that only 170 * the SystemUI can launch this activity. Activities that are not properly protected will not 171 * be launched. 172 * 173 * <p class="note">This is currently only used on TV to allow a system app to handle the 174 * notification panel. The package handling the notification panel has to be specified by 175 * config_notificationHandlerPackage in values/config.xml. 176 * 177 * Input: nothing 178 * Output: nothing 179 * @hide 180 */ 181 @SystemApi 182 @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 183 @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) 184 public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = 185 "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL"; 186 187 /** 188 * Activity action: Open notification panel of the specified handler. 189 * 190 * <p><strong>Important:</strong>You must protect the activity that handles this action with 191 * the {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission to ensure that only 192 * the SystemUI can launch this activity. Activities that are not properly protected will 193 * not be launched. 194 * 195 * <p class="note"> This is currently only used on TV to allow a system app to handle the 196 * notification panel. The package handling the notification panel has to be specified by 197 * config_notificationHandlerPackage in values/config.xml. 198 * 199 * Input: nothing 200 * Output: nothing 201 * @hide 202 */ 203 @SystemApi 204 @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 205 @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) 206 public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = 207 "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL"; 208 209 /** 210 * Intent that is broadcast when the notification panel of the specified handler is to be 211 * closed. 212 * 213 * <p><strong>Important:</strong>You should protect the receiver that handles this action with 214 * the {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission to ensure that only 215 * the SystemUI can send this broadcast to the notification handler. 216 * 217 * <p class="note"> This is currently only used on TV to allow a system app to handle the 218 * notification panel. The package handling the notification panel has to be specified by 219 * config_notificationHandlerPackage in values/config.xml. This is a protected intent that can 220 * only be sent by the system. 221 * 222 * Input: nothing. 223 * Output: nothing. 224 * @hide 225 */ 226 @SystemApi 227 @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) 228 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 229 public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = 230 "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL"; 231 232 /** 233 * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} containing the id of the 234 * {@link NotificationChannel} which has a new blocked state. 235 * 236 * The value will be the {@link NotificationChannel#getId()} of the channel. 237 */ 238 public static final String EXTRA_NOTIFICATION_CHANNEL_ID = 239 "android.app.extra.NOTIFICATION_CHANNEL_ID"; 240 241 /** 242 * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED} containing the id 243 * of the {@link NotificationChannelGroup} which has a new blocked state. 244 * 245 * The value will be the {@link NotificationChannelGroup#getId()} of the group. 246 */ 247 public static final String EXTRA_NOTIFICATION_CHANNEL_GROUP_ID = 248 "android.app.extra.NOTIFICATION_CHANNEL_GROUP_ID"; 249 250 251 /** 252 * Extra for {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} or 253 * {@link #ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED} containing the new blocked 254 * state as a boolean. 255 * 256 * The value will be {@code true} if this channel or group is now blocked and {@code false} if 257 * this channel or group is now unblocked. 258 */ 259 public static final String EXTRA_BLOCKED_STATE = "android.app.extra.BLOCKED_STATE"; 260 261 /** 262 * Intent that is broadcast when a {@link NotificationChannelGroup} is 263 * {@link NotificationChannelGroup#isBlocked() blocked} or unblocked. 264 * 265 * This broadcast is only sent to the app that owns the channel group that has changed. 266 * 267 * Input: nothing 268 * Output: {@link #EXTRA_NOTIFICATION_CHANNEL_GROUP_ID} 269 * Output: {@link #EXTRA_BLOCKED_STATE} 270 */ 271 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 272 public static final String ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED = 273 "android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED"; 274 275 /** 276 * Intent that is broadcast when the status of an {@link AutomaticZenRule} has changed. 277 * 278 * <p>Use this to know whether you need to continue monitor to device state in order to 279 * provide up-to-date states (with {@link #setAutomaticZenRuleState(String, Condition)}) for 280 * this rule.</p> 281 * 282 * Input: nothing 283 * Output: {@link #EXTRA_AUTOMATIC_ZEN_RULE_ID} 284 * Output: {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} 285 */ 286 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 287 public static final String ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED = 288 "android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED"; 289 290 /** 291 * Integer extra for {@link #ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED} containing the state of 292 * the {@link AutomaticZenRule}. 293 * 294 * <p>The value will be one of {@link #AUTOMATIC_RULE_STATUS_ENABLED}, 295 * {@link #AUTOMATIC_RULE_STATUS_DISABLED}, {@link #AUTOMATIC_RULE_STATUS_REMOVED}, 296 * {@link #AUTOMATIC_RULE_STATUS_ACTIVATED}, {@link #AUTOMATIC_RULE_STATUS_DEACTIVATED}, or 297 * {@link #AUTOMATIC_RULE_STATUS_UNKNOWN}. 298 * 299 * <p>Note that the {@link #AUTOMATIC_RULE_STATUS_ACTIVATED} and 300 * {@link #AUTOMATIC_RULE_STATUS_DEACTIVATED} statuses are only sent to packages targeting 301 * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above; apps targeting a lower SDK version 302 * will be sent {@link #AUTOMATIC_RULE_STATUS_UNKNOWN} in their place instead. 303 */ 304 public static final String EXTRA_AUTOMATIC_ZEN_RULE_STATUS = 305 "android.app.extra.AUTOMATIC_ZEN_RULE_STATUS"; 306 307 /** 308 * String extra for {@link #ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED} containing the id of the 309 * {@link AutomaticZenRule} (see {@link #addAutomaticZenRule(AutomaticZenRule)}) that has 310 * changed. 311 */ 312 public static final String EXTRA_AUTOMATIC_ZEN_RULE_ID = 313 "android.app.extra.AUTOMATIC_ZEN_RULE_ID"; 314 315 /** @hide */ 316 @IntDef(prefix = { "AUTOMATIC_RULE_STATUS" }, value = { 317 AUTOMATIC_RULE_STATUS_ENABLED, AUTOMATIC_RULE_STATUS_DISABLED, 318 AUTOMATIC_RULE_STATUS_REMOVED, AUTOMATIC_RULE_STATUS_UNKNOWN, 319 AUTOMATIC_RULE_STATUS_ACTIVATED, AUTOMATIC_RULE_STATUS_DEACTIVATED 320 }) 321 @Retention(RetentionPolicy.SOURCE) 322 public @interface AutomaticZenRuleStatus {} 323 324 /** 325 * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the current status of the 326 * rule is unknown at your target sdk version, and you should continue to provide state changes 327 * via {@link #setAutomaticZenRuleState(String, Condition)}. 328 */ 329 public static final int AUTOMATIC_RULE_STATUS_UNKNOWN = -1; 330 331 /** 332 * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule currently 333 * exists and is enabled. You should continue to provide state changes via 334 * {@link #setAutomaticZenRuleState(String, Condition)}. 335 */ 336 public static final int AUTOMATIC_RULE_STATUS_ENABLED = 1; 337 338 /** 339 * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule currently 340 * exists but is disabled. You do not need to continue to provide state changes via 341 * {@link #setAutomaticZenRuleState(String, Condition)} until the rule is reenabled. 342 */ 343 public static final int AUTOMATIC_RULE_STATUS_DISABLED = 2; 344 345 /** 346 * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule has been 347 * deleted. Further calls to {@link #setAutomaticZenRuleState(String, Condition)} will be 348 * ignored. 349 */ 350 public static final int AUTOMATIC_RULE_STATUS_REMOVED = 3; 351 352 /** 353 * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule has been 354 * activated by the user or cross device sync. Sent from 355 * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. If the rule owner has a mode that includes 356 * a DND component, the rule owner should activate any extra behavior that's part of that mode 357 * in response to this broadcast. 358 */ 359 public static final int AUTOMATIC_RULE_STATUS_ACTIVATED = 4; 360 361 /** 362 * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule has been 363 * deactivated ("snoozed") by the user. The rule will not return to an activated state until 364 * the app calls {@link #setAutomaticZenRuleState(String, Condition)} with 365 * {@link Condition#STATE_FALSE} (either immediately or when the trigger criteria is no 366 * longer met) and then {@link Condition#STATE_TRUE} when the trigger criteria is freshly met, 367 * or when the user re-activates it. 368 */ 369 public static final int AUTOMATIC_RULE_STATUS_DEACTIVATED = 5; 370 371 /** 372 * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes. 373 * 374 * <p>This broadcast is only sent to registered receivers and (starting from 375 * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not 376 * Disturb access (see {@link #isNotificationPolicyAccessGranted()}). 377 * 378 * @hide 379 */ 380 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 381 public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED 382 = "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED"; 383 384 /** 385 * Intent that is broadcast when the state of {@link #isNotificationPolicyAccessGranted()} 386 * changes. 387 * 388 * This broadcast is only sent to registered receivers, and only to the apps that have changed. 389 */ 390 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 391 public static final String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED 392 = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED"; 393 394 /** 395 * Intent that is broadcast when the state of {@link #getNotificationPolicy()} changes. 396 * 397 * <p>This broadcast is only sent to registered receivers and (starting from 398 * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not 399 * Disturb access (see {@link #isNotificationPolicyAccessGranted()}). 400 * 401 * <p>Starting with {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, most calls to 402 * {@link #setNotificationPolicy(Policy)} will update the app's implicit rule policy instead of 403 * the global policy, so this broadcast will be sent much less frequently. 404 */ 405 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 406 public static final String ACTION_NOTIFICATION_POLICY_CHANGED 407 = "android.app.action.NOTIFICATION_POLICY_CHANGED"; 408 409 /** 410 * Intent that is broadcast when the state of {@link #getConsolidatedNotificationPolicy()} 411 * changes. 412 * 413 * <p>This broadcast is only sent to registered receivers and receivers in packages that have 414 * been granted Notification Policy access (see {@link #isNotificationPolicyAccessGranted()}). 415 */ 416 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 417 public static final String ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED = 418 "android.app.action.CONSOLIDATED_NOTIFICATION_POLICY_CHANGED"; 419 420 /** 421 * Extra for {@link #ACTION_NOTIFICATION_POLICY_CHANGED} and 422 * {@link #ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED} containing the new 423 * {@link Policy} value. 424 */ 425 public static final String EXTRA_NOTIFICATION_POLICY = 426 "android.app.extra.NOTIFICATION_POLICY"; 427 428 /** 429 * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes. 430 * 431 * <p>This broadcast is only sent to registered receivers and (starting from 432 * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not 433 * Disturb access (see {@link #isNotificationPolicyAccessGranted()}). 434 */ 435 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 436 public static final String ACTION_INTERRUPTION_FILTER_CHANGED 437 = "android.app.action.INTERRUPTION_FILTER_CHANGED"; 438 439 /** 440 * Intent that is broadcast when the state of 441 * {@link #hasEnabledNotificationListener(String, UserHandle)} changes. 442 * @hide 443 */ 444 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 445 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 446 public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = 447 "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED"; 448 449 /** 450 * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes. 451 * @hide 452 */ 453 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 454 public static final String ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL 455 = "android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL"; 456 457 /** @hide */ 458 @IntDef(prefix = { "INTERRUPTION_FILTER_" }, value = { 459 INTERRUPTION_FILTER_NONE, INTERRUPTION_FILTER_PRIORITY, INTERRUPTION_FILTER_ALARMS, 460 INTERRUPTION_FILTER_ALL, INTERRUPTION_FILTER_UNKNOWN 461 }) 462 @Retention(RetentionPolicy.SOURCE) 463 public @interface InterruptionFilter {} 464 465 /** 466 * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 467 * Normal interruption filter - no notifications are suppressed. 468 */ 469 public static final int INTERRUPTION_FILTER_ALL = 1; 470 471 /** 472 * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 473 * Priority interruption filter - all notifications are suppressed except those that match 474 * the priority criteria. Some audio streams are muted. See 475 * {@link Policy#priorityCallSenders}, {@link Policy#priorityCategories}, 476 * {@link Policy#priorityMessageSenders} to define or query this criteria. Users can 477 * additionally specify packages that can bypass this interruption filter. 478 */ 479 public static final int INTERRUPTION_FILTER_PRIORITY = 2; 480 481 /** 482 * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 483 * No interruptions filter - all notifications are suppressed and all audio streams (except 484 * those used for phone calls) and vibrations are muted. 485 */ 486 public static final int INTERRUPTION_FILTER_NONE = 3; 487 488 /** 489 * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 490 * Alarms only interruption filter - all notifications except those of category 491 * {@link Notification#CATEGORY_ALARM} are suppressed. Some audio streams are muted. 492 */ 493 public static final int INTERRUPTION_FILTER_ALARMS = 4; 494 495 /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when 496 * the value is unavailable for any reason. 497 */ 498 public static final int INTERRUPTION_FILTER_UNKNOWN = 0; 499 500 /** @hide */ 501 @IntDef(prefix = { "IMPORTANCE_" }, value = { 502 IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE, 503 IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH 504 }) 505 @Retention(RetentionPolicy.SOURCE) 506 public @interface Importance {} 507 508 /** @hide */ 509 @IntDef(prefix = { "BUBBLE_PREFERENCE_" }, value = { 510 BUBBLE_PREFERENCE_NONE, BUBBLE_PREFERENCE_SELECTED, 511 BUBBLE_PREFERENCE_ALL 512 }) 513 @Retention(RetentionPolicy.SOURCE) 514 public @interface BubblePreference {} 515 516 /** 517 * Activity Action: Launch an Automatic Zen Rule configuration screen 518 * 519 * <p> Input: Optionally, {@link #EXTRA_AUTOMATIC_RULE_ID}, if the configuration screen for an 520 * existing rule should be displayed. If the rule id is missing or null, apps should display 521 * a configuration screen where users can create a new instance of the rule. 522 * 523 * <p> Output: Nothing 524 * 525 * <p> You can have multiple activities handling this intent, if you support multiple 526 * {@link AutomaticZenRule rules}. In order for the system to properly display all of your 527 * rule types so that users can create new instances or configure existing ones, you need 528 * to add some extra metadata ({@link #META_DATA_AUTOMATIC_RULE_TYPE}) 529 * to your activity tag in your manifest. If you'd like to limit the number of rules a user 530 * can create from this flow, you can additionally optionally include 531 * {@link #META_DATA_RULE_INSTANCE_LIMIT}. For example, 532 * 533 * <pre> 534 * {@code 535 * <meta-data 536 * android:name="android.service.zen.automatic.ruleType" 537 * android:value="@string/my_condition_rule" /> 538 * <meta-data 539 * android:name="android.service.zen.automatic.ruleInstanceLimit" 540 * android:value="1" /> 541 * } 542 * </pre> 543 * 544 * @see #addAutomaticZenRule(AutomaticZenRule) 545 */ 546 @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) 547 public static final String ACTION_AUTOMATIC_ZEN_RULE = 548 "android.app.action.AUTOMATIC_ZEN_RULE"; 549 550 /** 551 * Used as an optional string extra on {@link #ACTION_AUTOMATIC_ZEN_RULE} intents. If 552 * provided, contains the id of the {@link AutomaticZenRule} (as returned from 553 * {@link NotificationManager#addAutomaticZenRule(AutomaticZenRule)}) for which configuration 554 * settings should be displayed. 555 */ 556 public static final String EXTRA_AUTOMATIC_RULE_ID = "android.app.extra.AUTOMATIC_RULE_ID"; 557 558 /** 559 * A required {@code meta-data} tag for activities that handle 560 * {@link #ACTION_AUTOMATIC_ZEN_RULE}. 561 * 562 * This tag should contain a localized name of the type of the zen rule provided by the 563 * activity. 564 */ 565 public static final String META_DATA_AUTOMATIC_RULE_TYPE = 566 "android.service.zen.automatic.ruleType"; 567 568 /** 569 * An optional {@code meta-data} tag for activities that handle 570 * {@link #ACTION_AUTOMATIC_ZEN_RULE}. 571 * 572 * This tag should contain the maximum number of rule instances that 573 * can be created for this rule type. Omit or enter a value <= 0 to allow unlimited instances. 574 */ 575 public static final String META_DATA_RULE_INSTANCE_LIMIT = 576 "android.service.zen.automatic.ruleInstanceLimit"; 577 578 /** Value signifying that the user has not expressed a per-app visibility override value. 579 * @hide */ 580 public static final int VISIBILITY_NO_OVERRIDE = -1000; 581 582 /** 583 * Value signifying that the user has not expressed an importance. 584 * 585 * This value is for persisting preferences, and should never be associated with 586 * an actual notification. 587 */ 588 public static final int IMPORTANCE_UNSPECIFIED = -1000; 589 590 /** 591 * A notification with no importance: does not show in the shade. 592 */ 593 public static final int IMPORTANCE_NONE = 0; 594 595 /** 596 * Min notification importance: only shows in the shade, below the fold. This should 597 * not be used with {@link Service#startForeground(int, Notification) Service.startForeground} 598 * since a foreground service is supposed to be something the user cares about so it does 599 * not make semantic sense to mark its notification as minimum importance. If you do this 600 * as of Android version {@link android.os.Build.VERSION_CODES#O}, the system will show 601 * a higher-priority notification about your app running in the background. 602 */ 603 public static final int IMPORTANCE_MIN = 1; 604 605 /** 606 * Low notification importance: Shows in the shade, and potentially in the status bar 607 * (see {@link #shouldHideSilentStatusBarIcons()}), but is not audibly intrusive. 608 */ 609 public static final int IMPORTANCE_LOW = 2; 610 611 /** 612 * Default notification importance: shows everywhere, makes noise, but does not visually 613 * intrude. 614 */ 615 public static final int IMPORTANCE_DEFAULT = 3; 616 617 /** 618 * Higher notification importance: shows everywhere, makes noise and peeks. May use full screen 619 * intents. 620 */ 621 public static final int IMPORTANCE_HIGH = 4; 622 623 /** 624 * Unused. 625 */ 626 public static final int IMPORTANCE_MAX = 5; 627 628 /** 629 * Indicates that the no bubbles are allowed from the app. If the app sends bubbles, only the 630 * notification will appear. The notification will have an affordance allowing the user to 631 * bubble it. If the user selects this affordance, that notification is approved to bubble 632 * and the apps' bubble preference will be upgraded to {@link #BUBBLE_PREFERENCE_SELECTED}. 633 */ 634 public static final int BUBBLE_PREFERENCE_NONE = 0; 635 636 /** 637 * Indicates that all bubbles are allowed from the app. If the app sends bubbles, the bubble 638 * will appear along with the notification. 639 */ 640 public static final int BUBBLE_PREFERENCE_ALL = 1; 641 642 /** 643 * Indicates that only notifications selected by the user will appear as bubbles. If 644 * the app sends bubbles that haven't been selected, only the notification appear. If the 645 * bubble has been approved by the user, it will appear along with the notification. 646 */ 647 public static final int BUBBLE_PREFERENCE_SELECTED = 2; 648 649 /** 650 * Maximum length of the component name of a registered NotificationListenerService. 651 * @hide 652 */ 653 public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500; 654 655 private static final float MAX_NOTIFICATION_UPDATE_RATE = 5f; 656 private static final float MAX_NOTIFICATION_UNNECESSARY_CANCEL_RATE = 5f; 657 private static final int KNOWN_STATUS_ENQUEUED = 1; 658 private static final int KNOWN_STATUS_CANCELLED = 2; 659 660 private final Context mContext; 661 private final Map<CallNotificationEventListener, CallNotificationEventCallbackStub> 662 mCallNotificationEventCallbacks = new HashMap<>(); 663 664 private final InstantSource mClock; 665 private final RateLimiter mUpdateRateLimiter = new RateLimiter("notify (update)", 666 "notifications.value_client_throttled_notify_update", 667 MAX_NOTIFICATION_UPDATE_RATE); 668 private final RateLimiter mUnnecessaryCancelRateLimiter = new RateLimiter("cancel (dupe)", 669 "notifications.value_client_throttled_cancel_duplicate", 670 MAX_NOTIFICATION_UNNECESSARY_CANCEL_RATE); 671 // Value is KNOWN_STATUS_ENQUEUED/_CANCELLED 672 private final LruCache<NotificationKey, Integer> mKnownNotifications = new LruCache<>(100); 673 private final Object mThrottleLock = new Object(); 674 675 @UnsupportedAppUsage 676 private static INotificationManager sService; 677 678 /** @hide */ 679 @UnsupportedAppUsage getService()680 static public INotificationManager getService() 681 { 682 if (sService != null) { 683 return sService; 684 } 685 IBinder b = ServiceManager.getService("notification"); 686 sService = INotificationManager.Stub.asInterface(b); 687 return sService; 688 } 689 690 /** @hide */ service()691 protected INotificationManager service() { 692 return getService(); 693 } 694 695 /** {@hide} */ NotificationManager(Context context)696 public NotificationManager(Context context) 697 { 698 this(context, SystemClock.elapsedRealtimeClock()); 699 } 700 701 /** {@hide} */ 702 @UnsupportedAppUsage NotificationManager(Context context, InstantSource clock)703 public NotificationManager(Context context, InstantSource clock) { 704 mContext = context; 705 mClock = clock; 706 } 707 708 /** {@hide} */ 709 @UnsupportedAppUsage from(Context context)710 public static NotificationManager from(Context context) { 711 return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 712 } 713 714 /** 715 * Post a notification to be shown in the status bar. If a notification with 716 * the same id has already been posted by your application and has not yet been canceled, it 717 * will be replaced by the updated information. 718 * 719 * @param id An identifier for this notification unique within your 720 * application. 721 * @param notification A {@link Notification} object describing what to show the user. Must not 722 * be null. 723 */ notify(int id, Notification notification)724 public void notify(int id, Notification notification) 725 { 726 notify(null, id, notification); 727 } 728 729 /** 730 * Posts a notification to be shown in the status bar. If a notification with 731 * the same tag and id has already been posted by your application and has not yet been 732 * canceled, it will be replaced by the updated information. 733 * 734 * All {@link android.service.notification.NotificationListenerService listener services} will 735 * be granted {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} access to any {@link Uri uris} 736 * provided on this notification or the 737 * {@link NotificationChannel} this notification is posted to using 738 * {@link Context#grantUriPermission(String, Uri, int)}. Permission will be revoked when the 739 * notification is canceled, or you can revoke permissions with 740 * {@link Context#revokeUriPermission(Uri, int)}. 741 * 742 * @param tag A string identifier for this notification. May be {@code null}. 743 * @param id An identifier for this notification. The pair (tag, id) must be unique 744 * within your application. 745 * @param notification A {@link Notification} object describing what to 746 * show the user. Must not be null. 747 */ notify(String tag, int id, Notification notification)748 public void notify(String tag, int id, Notification notification) 749 { 750 notifyAsUser(tag, id, notification, mContext.getUser()); 751 } 752 753 /** 754 * Posts a notification as a specified package to be shown in the status bar. If a notification 755 * with the same tag and id has already been posted for that package and has not yet been 756 * canceled, it will be replaced by the updated information. 757 * 758 * All {@link android.service.notification.NotificationListenerService listener services} will 759 * be granted {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} access to any {@link Uri uris} 760 * provided on this notification or the 761 * {@link NotificationChannel} this notification is posted to using 762 * {@link Context#grantUriPermission(String, Uri, int)}. Permission will be revoked when the 763 * notification is canceled, or you can revoke permissions with 764 * {@link Context#revokeUriPermission(Uri, int)}. 765 * 766 * @param targetPackage The package to post the notification as. The package must have granted 767 * you access to post notifications on their behalf with 768 * {@link #setNotificationDelegate(String)}. 769 * @param tag A string identifier for this notification. May be {@code null}. 770 * @param id An identifier for this notification. The pair (tag, id) must be unique 771 * within your application. 772 * @param notification A {@link Notification} object describing what to 773 * show the user. Must not be null. 774 */ notifyAsPackage(@onNull String targetPackage, @Nullable String tag, int id, @NonNull Notification notification)775 public void notifyAsPackage(@NonNull String targetPackage, @Nullable String tag, int id, 776 @NonNull Notification notification) { 777 INotificationManager service = service(); 778 String sender = mContext.getPackageName(); 779 780 if (discardNotify(mContext.getUser(), targetPackage, tag, id, notification)) { 781 return; 782 } 783 784 try { 785 if (localLOGV) Log.v(TAG, sender + ": notify(" + id + ", " + notification + ")"); 786 service.enqueueNotificationWithTag(targetPackage, sender, tag, id, 787 fixNotification(notification), mContext.getUser().getIdentifier()); 788 } catch (RemoteException e) { 789 throw e.rethrowFromSystemServer(); 790 } 791 } 792 793 /** 794 * @hide 795 */ 796 @UnsupportedAppUsage notifyAsUser(@ullable String tag, int id, Notification notification, UserHandle user)797 public void notifyAsUser(@Nullable String tag, int id, Notification notification, 798 UserHandle user) 799 { 800 INotificationManager service = service(); 801 String pkg = mContext.getPackageName(); 802 if (discardNotify(user, pkg, tag, id, notification)) { 803 return; 804 } 805 806 try { 807 if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); 808 service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id, 809 fixNotification(notification), user.getIdentifier()); 810 } catch (RemoteException e) { 811 throw e.rethrowFromSystemServer(); 812 } 813 } 814 815 /** 816 * Determines whether a {@link #notify} call should be skipped. If the notification is not 817 * skipped, updates tracking metadata to use in future decisions. 818 */ discardNotify(UserHandle user, String pkg, @Nullable String tag, int id, Notification notification)819 private boolean discardNotify(UserHandle user, String pkg, @Nullable String tag, int id, 820 Notification notification) { 821 if (notificationClassification() 822 && NotificationChannel.SYSTEM_RESERVED_IDS.contains(notification.getChannelId())) { 823 return true; 824 } 825 826 if (Flags.nmBinderPerfThrottleNotify()) { 827 NotificationKey key = new NotificationKey(user, pkg, tag, id); 828 synchronized (mThrottleLock) { 829 Integer status = mKnownNotifications.get(key); 830 if (status != null && status == KNOWN_STATUS_ENQUEUED 831 && !notification.hasCompletedProgress()) { 832 if (mUpdateRateLimiter.eventExceedsRate()) { 833 mUpdateRateLimiter.recordRejected(key); 834 return true; 835 } 836 mUpdateRateLimiter.recordAccepted(); 837 } 838 mKnownNotifications.put(key, KNOWN_STATUS_ENQUEUED); 839 } 840 } 841 842 return false; 843 } 844 NotificationKey(@onNull UserHandle user, @NonNull String pkg, @Nullable String tag, int id)845 private record NotificationKey(@NonNull UserHandle user, @NonNull String pkg, 846 @Nullable String tag, int id) { } 847 848 /** Helper class to rate-limit Binder calls. */ 849 private class RateLimiter { 850 851 private static final Duration RATE_LIMITER_LOG_INTERVAL = Duration.ofSeconds(1); 852 853 private final RateEstimator mInputRateEstimator; 854 private final RateEstimator mOutputRateEstimator; 855 private final String mName; 856 private final String mCounterName; 857 private final float mLimitRate; 858 859 private Instant mLogSilencedUntil; 860 RateLimiter(String name, String counterName, float limitRate)861 private RateLimiter(String name, String counterName, float limitRate) { 862 mInputRateEstimator = new RateEstimator(); 863 mOutputRateEstimator = new RateEstimator(); 864 mName = name; 865 mCounterName = counterName; 866 mLimitRate = limitRate; 867 } 868 eventExceedsRate()869 boolean eventExceedsRate() { 870 long nowMillis = mClock.millis(); 871 mInputRateEstimator.update(nowMillis); 872 return mOutputRateEstimator.getRate(nowMillis) > mLimitRate; 873 } 874 recordAccepted()875 void recordAccepted() { 876 mOutputRateEstimator.update(mClock.millis()); 877 } 878 recordRejected(NotificationKey key)879 void recordRejected(NotificationKey key) { 880 Instant now = mClock.instant(); 881 if (mLogSilencedUntil != null && now.isBefore(mLogSilencedUntil)) { 882 return; 883 } 884 885 if (Flags.nmBinderPerfLogNmThrottling()) { 886 try { 887 service().incrementCounter(mCounterName); 888 } catch (RemoteException e) { 889 Slog.w(TAG, "Ignoring error while trying to log " + mCounterName, e); 890 } 891 } 892 893 long nowMillis = now.toEpochMilli(); 894 Slog.w(TAG, TextUtils.formatSimple( 895 "Shedding %s of %s, rate limit (%s) exceeded: input %s, output would be %s", 896 mName, key, mLimitRate, mInputRateEstimator.getRate(nowMillis), 897 mOutputRateEstimator.getRate(nowMillis))); 898 899 mLogSilencedUntil = now.plus(RATE_LIMITER_LOG_INTERVAL); 900 } 901 } 902 fixNotification(Notification notification)903 private Notification fixNotification(Notification notification) { 904 String pkg = mContext.getPackageName(); 905 // Fix the notification as best we can. 906 Notification.addFieldsFromContext(mContext, notification); 907 908 if (notification.sound != null) { 909 notification.sound = notification.sound.getCanonicalUri(); 910 if (StrictMode.vmFileUriExposureEnabled()) { 911 notification.sound.checkFileUriExposed("Notification.sound"); 912 } 913 914 } 915 fixLegacySmallIcon(notification, pkg); 916 if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { 917 if (notification.getSmallIcon() == null) { 918 throw new IllegalArgumentException("Invalid notification (no valid small icon): " 919 + notification); 920 } 921 } 922 923 notification.reduceImageSizes(mContext); 924 return Builder.maybeCloneStrippedForDelivery(notification); 925 } 926 fixLegacySmallIcon(Notification n, String pkg)927 private void fixLegacySmallIcon(Notification n, String pkg) { 928 if (n.getSmallIcon() == null && n.icon != 0) { 929 n.setSmallIcon(Icon.createWithResource(pkg, n.icon)); 930 } 931 } 932 933 /** 934 * Cancels a previously posted notification. 935 * 936 * <p>If the notification does not currently represent a 937 * {@link Service#startForeground(int, Notification) foreground service} or a 938 * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job}, 939 * it will be removed from the UI and live 940 * {@link android.service.notification.NotificationListenerService notification listeners} 941 * will be informed so they can remove the notification from their UIs.</p> 942 */ cancel(int id)943 public void cancel(int id) 944 { 945 cancel(null, id); 946 } 947 948 /** 949 * Cancels a previously posted notification. 950 * 951 * <p>If the notification does not currently represent a 952 * {@link Service#startForeground(int, Notification) foreground service} or a 953 * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job}, 954 * it will be removed from the UI and live 955 * {@link android.service.notification.NotificationListenerService notification listeners} 956 * will be informed so they can remove the notification from their UIs.</p> 957 */ cancel(@ullable String tag, int id)958 public void cancel(@Nullable String tag, int id) 959 { 960 cancelAsUser(tag, id, mContext.getUser()); 961 } 962 963 /** 964 * Cancels a previously posted notification. 965 * 966 * <p>If the notification does not currently represent a 967 * {@link Service#startForeground(int, Notification) foreground service} or a 968 * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job}, 969 * it will be removed from the UI and live 970 * {@link android.service.notification.NotificationListenerService notification listeners} 971 * will be informed so they can remove the notification from their UIs.</p> 972 * 973 * <p>This method may be used by {@link #getNotificationDelegate() a notification delegate} to 974 * cancel notifications that they have posted via {@link #notifyAsPackage(String, String, int, 975 * Notification)}.</p> 976 * 977 * @param targetPackage The package to cancel the notification as. If this package is not your 978 * package, you can only cancel notifications you posted with 979 * {@link #notifyAsPackage(String, String, int, Notification). 980 * @param tag A string identifier for this notification. May be {@code null}. 981 * @param id An identifier for this notification. 982 */ cancelAsPackage(@onNull String targetPackage, @Nullable String tag, int id)983 public void cancelAsPackage(@NonNull String targetPackage, @Nullable String tag, int id) { 984 if (discardCancel(mContext.getUser(), targetPackage, tag, id)) { 985 return; 986 } 987 988 INotificationManager service = service(); 989 try { 990 service.cancelNotificationWithTag(targetPackage, mContext.getOpPackageName(), 991 tag, id, mContext.getUser().getIdentifier()); 992 } catch (RemoteException e) { 993 throw e.rethrowFromSystemServer(); 994 } 995 } 996 997 /** 998 * @hide 999 */ 1000 @UnsupportedAppUsage cancelAsUser(@ullable String tag, int id, UserHandle user)1001 public void cancelAsUser(@Nullable String tag, int id, UserHandle user) 1002 { 1003 String pkg = mContext.getPackageName(); 1004 if (discardCancel(user, pkg, tag, id)) { 1005 return; 1006 } 1007 1008 INotificationManager service = service(); 1009 if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")"); 1010 try { 1011 service.cancelNotificationWithTag( 1012 pkg, mContext.getOpPackageName(), tag, id, user.getIdentifier()); 1013 } catch (RemoteException e) { 1014 throw e.rethrowFromSystemServer(); 1015 } 1016 } 1017 1018 /** 1019 * Determines whether a {@link #cancel} call should be skipped. If not skipped, updates tracking 1020 * metadata to use in future decisions. 1021 */ discardCancel(UserHandle user, String pkg, @Nullable String tag, int id)1022 private boolean discardCancel(UserHandle user, String pkg, @Nullable String tag, int id) { 1023 if (Flags.nmBinderPerfThrottleNotify()) { 1024 NotificationKey key = new NotificationKey(user, pkg, tag, id); 1025 synchronized (mThrottleLock) { 1026 Integer status = mKnownNotifications.get(key); 1027 if (status != null && status == KNOWN_STATUS_CANCELLED) { 1028 if (mUnnecessaryCancelRateLimiter.eventExceedsRate()) { 1029 mUnnecessaryCancelRateLimiter.recordRejected(key); 1030 return true; 1031 } 1032 mUnnecessaryCancelRateLimiter.recordAccepted(); 1033 } 1034 mKnownNotifications.put(key, KNOWN_STATUS_CANCELLED); 1035 } 1036 } 1037 1038 return false; 1039 } 1040 1041 /** 1042 * Cancel all previously shown notifications. See {@link #cancel} for the 1043 * detailed behavior. 1044 */ cancelAll()1045 public void cancelAll() 1046 { 1047 String pkg = mContext.getPackageName(); 1048 UserHandle user = mContext.getUser(); 1049 1050 if (Flags.nmBinderPerfThrottleNotify()) { 1051 synchronized (mThrottleLock) { 1052 for (NotificationKey key : mKnownNotifications.snapshot().keySet()) { 1053 if (key.pkg.equals(pkg) && key.user.equals(user)) { 1054 mKnownNotifications.put(key, KNOWN_STATUS_CANCELLED); 1055 } 1056 } 1057 } 1058 } 1059 1060 INotificationManager service = service(); 1061 if (localLOGV) Log.v(TAG, pkg + ": cancelAll()"); 1062 try { 1063 service.cancelAllNotifications(pkg, mContext.getUserId()); 1064 } catch (RemoteException e) { 1065 throw e.rethrowFromSystemServer(); 1066 } 1067 } 1068 1069 /** 1070 * Allows a package to post notifications on your behalf using 1071 * {@link #notifyAsPackage(String, String, int, Notification)}. 1072 * 1073 * This can be used to allow persistent processes to post notifications based on messages 1074 * received on your behalf from the cloud, without your process having to wake up. 1075 * 1076 * You can check if you have an allowed delegate with {@link #getNotificationDelegate()} and 1077 * revoke your delegate by passing null to this method. 1078 * 1079 * @param delegate Package name of the app which can send notifications on your behalf. 1080 */ setNotificationDelegate(@ullable String delegate)1081 public void setNotificationDelegate(@Nullable String delegate) { 1082 INotificationManager service = service(); 1083 String pkg = mContext.getPackageName(); 1084 if (localLOGV) Log.v(TAG, pkg + ": setNotificationDelegate()"); 1085 try { 1086 service.setNotificationDelegate(pkg, delegate); 1087 } catch (RemoteException e) { 1088 throw e.rethrowFromSystemServer(); 1089 } 1090 } 1091 1092 /** 1093 * Returns the {@link #setNotificationDelegate(String) delegate} that can post notifications on 1094 * your behalf, if there currently is one. 1095 */ getNotificationDelegate()1096 public @Nullable String getNotificationDelegate() { 1097 INotificationManager service = service(); 1098 String pkg = mContext.getPackageName(); 1099 try { 1100 return service.getNotificationDelegate(pkg); 1101 } catch (RemoteException e) { 1102 throw e.rethrowFromSystemServer(); 1103 } 1104 } 1105 1106 /** 1107 * Returns whether you are allowed to post notifications on behalf of a given package, with 1108 * {@link #notifyAsPackage(String, String, int, Notification)}. 1109 * 1110 * See {@link #setNotificationDelegate(String)}. 1111 */ canNotifyAsPackage(@onNull String pkg)1112 public boolean canNotifyAsPackage(@NonNull String pkg) { 1113 INotificationManager service = service(); 1114 try { 1115 return service.canNotifyAsPackage(mContext.getPackageName(), pkg, mContext.getUserId()); 1116 } catch (RemoteException e) { 1117 throw e.rethrowFromSystemServer(); 1118 } 1119 } 1120 1121 /** 1122 * Returns whether the calling app can send fullscreen intents. 1123 * <p>From Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, apps may not have 1124 * permission to use {@link android.Manifest.permission#USE_FULL_SCREEN_INTENT}. If permission 1125 * is denied, notification will show up as an expanded heads up notification on lockscreen. 1126 * <p> To request access, add the {@link android.Manifest.permission#USE_FULL_SCREEN_INTENT} 1127 * permission to your manifest, and use 1128 * {@link android.provider.Settings#ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT}. 1129 */ canUseFullScreenIntent()1130 public boolean canUseFullScreenIntent() { 1131 INotificationManager service = service(); 1132 try { 1133 return service.canUseFullScreenIntent(mContext.getAttributionSource()); 1134 } catch (RemoteException e) { 1135 throw e.rethrowFromSystemServer(); 1136 } 1137 } 1138 1139 /** 1140 * Returns whether the calling app's properly formatted notifications can appear in a promoted 1141 * format, which may result in higher ranking, appearances on additional surfaces, and richer 1142 * presentation. 1143 * 1144 * Apps can request this permission by sending the user to the activity that matches the system 1145 * intent action {@link android.provider.Settings#ACTION_APP_NOTIFICATION_PROMOTION_SETTINGS}. 1146 */ 1147 @FlaggedApi(android.app.Flags.FLAG_API_RICH_ONGOING) canPostPromotedNotifications()1148 public boolean canPostPromotedNotifications() { 1149 INotificationManager service = service(); 1150 try { 1151 return service.canBePromoted(mContext.getPackageName()); 1152 } catch (RemoteException e) { 1153 throw e.rethrowFromSystemServer(); 1154 } 1155 } 1156 1157 /** 1158 * Setter for {@link #canPostPromotedNotifications()}. Only callable by the OS. 1159 * @hide 1160 */ 1161 @TestApi 1162 @FlaggedApi(android.app.Flags.FLAG_API_RICH_ONGOING) setCanPostPromotedNotifications(@onNull String pkg, int uid, boolean allowed)1163 public void setCanPostPromotedNotifications(@NonNull String pkg, int uid, boolean allowed) { 1164 INotificationManager service = service(); 1165 try { 1166 service.setCanBePromoted(pkg, uid, allowed, true); 1167 } catch (RemoteException e) { 1168 throw e.rethrowFromSystemServer(); 1169 } 1170 } 1171 1172 /** 1173 * Creates a group container for {@link NotificationChannel} objects. 1174 * 1175 * This can be used to rename an existing group. 1176 * <p> 1177 * Group information is only used for presentation, not for behavior. Groups are optional 1178 * for channels, and you can have a mix of channels that belong to groups and channels 1179 * that do not. 1180 * </p> 1181 * <p> 1182 * For example, if your application supports multiple accounts, and those accounts will 1183 * have similar channels, you can create a group for each account with account specific 1184 * labels instead of appending account information to each channel's label. 1185 * </p> 1186 * 1187 * @param group The group to create 1188 */ createNotificationChannelGroup(@onNull NotificationChannelGroup group)1189 public void createNotificationChannelGroup(@NonNull NotificationChannelGroup group) { 1190 createNotificationChannelGroups(Arrays.asList(group)); 1191 } 1192 1193 /** 1194 * Creates multiple notification channel groups. 1195 * 1196 * @param groups The list of groups to create 1197 */ createNotificationChannelGroups(@onNull List<NotificationChannelGroup> groups)1198 public void createNotificationChannelGroups(@NonNull List<NotificationChannelGroup> groups) { 1199 INotificationManager service = service(); 1200 try { 1201 service.createNotificationChannelGroups(mContext.getPackageName(), 1202 new ParceledListSlice(groups)); 1203 } catch (RemoteException e) { 1204 throw e.rethrowFromSystemServer(); 1205 } 1206 } 1207 1208 /** 1209 * Creates a notification channel that notifications can be posted to. 1210 * 1211 * This can also be used to restore a deleted channel and to update an existing channel's 1212 * name, description, group, and/or importance. 1213 * 1214 * <p>The name and description should only be changed if the locale changes 1215 * or in response to the user renaming this channel. For example, if a user has a channel 1216 * named 'Messages' and the user changes their locale, this channel's name should be updated 1217 * with the translation of 'Messages' in the new locale. 1218 * 1219 * <p>The importance of an existing channel will only be changed if the new importance is lower 1220 * than the current value and the user has not altered any settings on this channel. 1221 * 1222 * <p>The group an existing channel will only be changed if the channel does not already 1223 * belong to a group. 1224 * 1225 * All other fields are ignored for channels that already exist. 1226 * 1227 * @param channel the channel to create. Note that the created channel may differ from this 1228 * value. If the provided channel is malformed, a RemoteException will be 1229 * thrown. 1230 */ createNotificationChannel(@onNull NotificationChannel channel)1231 public void createNotificationChannel(@NonNull NotificationChannel channel) { 1232 createNotificationChannels(Arrays.asList(channel)); 1233 } 1234 1235 /** 1236 * Creates multiple notification channels that different notifications can be posted to. See 1237 * {@link #createNotificationChannel(NotificationChannel)}. 1238 * 1239 * @param channels the list of channels to attempt to create. 1240 */ createNotificationChannels(@onNull List<NotificationChannel> channels)1241 public void createNotificationChannels(@NonNull List<NotificationChannel> channels) { 1242 INotificationManager service = service(); 1243 try { 1244 service.createNotificationChannels(mContext.getPackageName(), 1245 new ParceledListSlice(channels)); 1246 } catch (RemoteException e) { 1247 throw e.rethrowFromSystemServer(); 1248 } 1249 } 1250 1251 /** 1252 * Returns the notification channel settings for a given channel id. 1253 * 1254 * <p>The channel must belong to your package, or to a package you are an approved notification 1255 * delegate for (see {@link #canNotifyAsPackage(String)}), or it will not be returned. To query 1256 * a channel as a notification delegate, call this method from a context created for that 1257 * package (see {@link Context#createPackageContext(String, int)}).</p> 1258 */ getNotificationChannel(String channelId)1259 public NotificationChannel getNotificationChannel(String channelId) { 1260 if (Flags.nmBinderPerfCacheChannels()) { 1261 return getChannelFromList(channelId, 1262 mNotificationChannelListCache.query(new NotificationChannelQuery( 1263 mContext.getOpPackageName(), 1264 mContext.getPackageName(), 1265 mContext.getUserId()))); 1266 } else { 1267 INotificationManager service = service(); 1268 try { 1269 return service.getNotificationChannel(mContext.getOpPackageName(), 1270 mContext.getUserId(), mContext.getPackageName(), channelId); 1271 } catch (RemoteException e) { 1272 throw e.rethrowFromSystemServer(); 1273 } 1274 } 1275 } 1276 1277 /** 1278 * Returns the notification channel settings for a given channel and 1279 * {@link ShortcutInfo#getId() conversation id}. 1280 * 1281 * <p>The channel must belong to your package, or to a package you are an approved notification 1282 * delegate for (see {@link #canNotifyAsPackage(String)}), or it will not be returned. To query 1283 * a channel as a notification delegate, call this method from a context created for that 1284 * package (see {@link Context#createPackageContext(String, int)}).</p> 1285 * 1286 * <p>If a conversation channel with the given conversation id is not found, this method will 1287 * instead return the parent channel with the given channel ID, or {@code null} if neither 1288 * exists.</p> 1289 */ getNotificationChannel(@onNull String channelId, @NonNull String conversationId)1290 public @Nullable NotificationChannel getNotificationChannel(@NonNull String channelId, 1291 @NonNull String conversationId) { 1292 if (Flags.nmBinderPerfCacheChannels()) { 1293 return getConversationChannelFromList(channelId, conversationId, 1294 mNotificationChannelListCache.query(new NotificationChannelQuery( 1295 mContext.getOpPackageName(), 1296 mContext.getPackageName(), 1297 mContext.getUserId()))); 1298 } else { 1299 INotificationManager service = service(); 1300 try { 1301 return service.getConversationNotificationChannel(mContext.getOpPackageName(), 1302 mContext.getUserId(), mContext.getPackageName(), channelId, true, 1303 conversationId); 1304 } catch (RemoteException e) { 1305 throw e.rethrowFromSystemServer(); 1306 } 1307 } 1308 } 1309 1310 /** 1311 * Returns all notification channels belonging to the calling package. 1312 * 1313 * <p>Approved notification delegates (see {@link #canNotifyAsPackage(String)}) can query 1314 * notification channels belonging to packages they are the delegate for. To do so, call this 1315 * method from a context created for that package (see 1316 * {@link Context#createPackageContext(String, int)}).</p> 1317 */ getNotificationChannels()1318 public List<NotificationChannel> getNotificationChannels() { 1319 if (Flags.nmBinderPerfCacheChannels()) { 1320 List<NotificationChannel> channelList = mNotificationChannelListCache.query( 1321 new NotificationChannelQuery(mContext.getOpPackageName(), 1322 mContext.getPackageName(), mContext.getUserId())); 1323 List<NotificationChannel> out = new ArrayList(); 1324 if (channelList != null) { 1325 for (NotificationChannel c : channelList) { 1326 out.add(c.copy()); 1327 } 1328 } 1329 return out; 1330 } else { 1331 INotificationManager service = service(); 1332 try { 1333 return service.getNotificationChannels(mContext.getOpPackageName(), 1334 mContext.getPackageName(), mContext.getUserId()).getList(); 1335 } catch (RemoteException e) { 1336 throw e.rethrowFromSystemServer(); 1337 } 1338 } 1339 } 1340 1341 // channel list assumed to be associated with the appropriate package & user id already. getChannelFromList(String channelId, List<NotificationChannel> channels)1342 private static NotificationChannel getChannelFromList(String channelId, 1343 List<NotificationChannel> channels) { 1344 if (channels == null) { 1345 return null; 1346 } 1347 if (channelId == null) { 1348 channelId = DEFAULT_CHANNEL_ID; 1349 } 1350 for (NotificationChannel channel : channels) { 1351 if (channelId.equals(channel.getId())) { 1352 return channel.copy(); 1353 } 1354 } 1355 return null; 1356 } 1357 getConversationChannelFromList(String channelId, String conversationId, List<NotificationChannel> channels)1358 private static NotificationChannel getConversationChannelFromList(String channelId, 1359 String conversationId, List<NotificationChannel> channels) { 1360 if (channels == null) { 1361 return null; 1362 } 1363 if (channelId == null) { 1364 channelId = DEFAULT_CHANNEL_ID; 1365 } 1366 if (conversationId == null) { 1367 return getChannelFromList(channelId, channels); 1368 } 1369 NotificationChannel parent = null; 1370 for (NotificationChannel channel : channels) { 1371 if (conversationId.equals(channel.getConversationId()) 1372 && channelId.equals(channel.getParentChannelId())) { 1373 return channel.copy(); 1374 } else if (channelId.equals(channel.getId())) { 1375 parent = channel; 1376 } 1377 } 1378 return parent != null ? parent.copy() : null; 1379 } 1380 1381 /** 1382 * Deletes the given notification channel. 1383 * 1384 * <p>If you {@link #createNotificationChannel(NotificationChannel) create} a new channel with 1385 * this same id, the deleted channel will be un-deleted with all of the same settings it 1386 * had before it was deleted. 1387 */ deleteNotificationChannel(String channelId)1388 public void deleteNotificationChannel(String channelId) { 1389 if (notificationClassification() 1390 && NotificationChannel.SYSTEM_RESERVED_IDS.contains(channelId)) { 1391 return; 1392 } 1393 INotificationManager service = service(); 1394 try { 1395 service.deleteNotificationChannel(mContext.getPackageName(), channelId); 1396 } catch (RemoteException e) { 1397 throw e.rethrowFromSystemServer(); 1398 } 1399 } 1400 1401 /** 1402 * Returns the notification channel group settings for a given channel group id. 1403 * 1404 * The channel group must belong to your package, or null will be returned. 1405 */ getNotificationChannelGroup(String channelGroupId)1406 public NotificationChannelGroup getNotificationChannelGroup(String channelGroupId) { 1407 if (Flags.nmBinderPerfCacheChannels()) { 1408 String pkgName = mContext.getPackageName(); 1409 // getNotificationChannelGroup may only be called by the same package. 1410 List<NotificationChannel> channelList = mNotificationChannelListCache.query( 1411 new NotificationChannelQuery(pkgName, pkgName, mContext.getUserId())); 1412 Map<String, NotificationChannelGroup> groupHeaders = 1413 mNotificationChannelGroupsCache.query(pkgName); 1414 NotificationChannelGroup ncg = NotificationChannelGroupsHelper.getGroupWithChannels( 1415 channelGroupId, channelList, groupHeaders, /* includeDeleted= */ false); 1416 return ncg != null ? ncg.clone() : null; 1417 } else { 1418 INotificationManager service = service(); 1419 try { 1420 return service.getNotificationChannelGroup(mContext.getPackageName(), 1421 channelGroupId); 1422 } catch (RemoteException e) { 1423 throw e.rethrowFromSystemServer(); 1424 } 1425 } 1426 } 1427 1428 /** 1429 * Returns all notification channel groups belonging to the calling app. 1430 */ getNotificationChannelGroups()1431 public List<NotificationChannelGroup> getNotificationChannelGroups() { 1432 if (Flags.nmBinderPerfCacheChannels()) { 1433 String pkgName = mContext.getPackageName(); 1434 List<NotificationChannel> channelList = mNotificationChannelListCache.query( 1435 new NotificationChannelQuery(pkgName, pkgName, mContext.getUserId())); 1436 Map<String, NotificationChannelGroup> groupHeaders = 1437 mNotificationChannelGroupsCache.query(pkgName); 1438 List<NotificationChannelGroup> populatedGroupList = 1439 NotificationChannelGroupsHelper.getGroupsWithChannels(channelList, groupHeaders, 1440 NotificationChannelGroupsHelper.Params.forAllGroups()); 1441 List<NotificationChannelGroup> out = new ArrayList<>(); 1442 for (NotificationChannelGroup g : populatedGroupList) { 1443 out.add(g.clone()); 1444 } 1445 return out; 1446 } else { 1447 INotificationManager service = service(); 1448 try { 1449 final ParceledListSlice<NotificationChannelGroup> parceledList = 1450 service.getNotificationChannelGroups(mContext.getPackageName()); 1451 if (parceledList != null) { 1452 return parceledList.getList(); 1453 } 1454 } catch (RemoteException e) { 1455 throw e.rethrowFromSystemServer(); 1456 } 1457 return new ArrayList<>(); 1458 } 1459 } 1460 1461 /** 1462 * Deletes the given notification channel group, and all notification channels that 1463 * belong to it. 1464 */ deleteNotificationChannelGroup(String groupId)1465 public void deleteNotificationChannelGroup(String groupId) { 1466 INotificationManager service = service(); 1467 try { 1468 service.deleteNotificationChannelGroup(mContext.getPackageName(), groupId); 1469 } catch (RemoteException e) { 1470 throw e.rethrowFromSystemServer(); 1471 } 1472 } 1473 1474 /** 1475 * @hide 1476 */ 1477 @TestApi updateNotificationChannel(@onNull String pkg, int uid, @NonNull NotificationChannel channel)1478 public void updateNotificationChannel(@NonNull String pkg, int uid, 1479 @NonNull NotificationChannel channel) { 1480 INotificationManager service = service(); 1481 try { 1482 service.updateNotificationChannelForPackage(pkg, uid, channel); 1483 } catch (RemoteException e) { 1484 throw e.rethrowFromSystemServer(); 1485 } 1486 } 1487 1488 private static final String NOTIFICATION_CHANNELS_CACHE_API = "getNotificationChannels"; 1489 private static final int NOTIFICATION_CHANNELS_CACHE_SIZE = 10; 1490 private static final String NOTIFICATION_CHANNEL_GROUPS_CACHE_API = 1491 "getNotificationChannelGroups"; 1492 private static final int NOTIFICATION_CHANNEL_GROUPS_CACHE_SIZE = 10; 1493 1494 private final IpcDataCache.QueryHandler<NotificationChannelQuery, List<NotificationChannel>> 1495 mNotificationChannelListQueryHandler = new IpcDataCache.QueryHandler<>() { 1496 @Override 1497 public List<NotificationChannel> apply(NotificationChannelQuery query) { 1498 INotificationManager service = service(); 1499 try { 1500 return service.getNotificationChannels(query.callingPkg, 1501 query.targetPkg, query.userId).getList(); 1502 } catch (RemoteException e) { 1503 throw e.rethrowFromSystemServer(); 1504 } 1505 } 1506 1507 @Override 1508 public boolean shouldBypassCache(@NonNull NotificationChannelQuery query) { 1509 // Other locations should also not be querying the cache in the first place if 1510 // the flag is not enabled, but this is an extra precaution. 1511 if (!Flags.nmBinderPerfCacheChannels()) { 1512 Log.wtf(TAG, 1513 "shouldBypassCache called when nm_binder_perf_cache_channels off"); 1514 return true; 1515 } 1516 return false; 1517 } 1518 }; 1519 1520 private final IpcDataCache<NotificationChannelQuery, List<NotificationChannel>> 1521 mNotificationChannelListCache = 1522 new IpcDataCache<>(NOTIFICATION_CHANNELS_CACHE_SIZE, IpcDataCache.MODULE_SYSTEM, 1523 NOTIFICATION_CHANNELS_CACHE_API, NOTIFICATION_CHANNELS_CACHE_API, 1524 mNotificationChannelListQueryHandler); 1525 NotificationChannelQuery( String callingPkg, String targetPkg, int userId)1526 private record NotificationChannelQuery( 1527 String callingPkg, 1528 String targetPkg, 1529 int userId) {} 1530 1531 private final IpcDataCache.QueryHandler<String, Map<String, NotificationChannelGroup>> 1532 mNotificationChannelGroupsQueryHandler = new IpcDataCache.QueryHandler<>() { 1533 @Override 1534 public Map<String, NotificationChannelGroup> apply(String pkg) { 1535 INotificationManager service = service(); 1536 Map<String, NotificationChannelGroup> groups = new ArrayMap<>(); 1537 try { 1538 final ParceledListSlice<NotificationChannelGroup> parceledList = 1539 service.getNotificationChannelGroupsWithoutChannels(pkg); 1540 if (parceledList != null) { 1541 for (NotificationChannelGroup group : parceledList.getList()) { 1542 groups.put(group.getId(), group); 1543 } 1544 } 1545 } catch (RemoteException e) { 1546 throw e.rethrowFromSystemServer(); 1547 } 1548 return groups; 1549 } 1550 1551 @Override 1552 public boolean shouldBypassCache(@NonNull String query) { 1553 // Other locations should also not be querying the cache in the first place if 1554 // the flag is not enabled, but this is an extra precaution. 1555 if (!Flags.nmBinderPerfCacheChannels()) { 1556 Log.wtf(TAG, 1557 "shouldBypassCache called when nm_binder_perf_cache_channels off"); 1558 return true; 1559 } 1560 return false; 1561 } 1562 }; 1563 1564 private final IpcDataCache<String, Map<String, NotificationChannelGroup>> 1565 mNotificationChannelGroupsCache = new IpcDataCache<>( 1566 NOTIFICATION_CHANNEL_GROUPS_CACHE_SIZE, IpcDataCache.MODULE_SYSTEM, 1567 NOTIFICATION_CHANNEL_GROUPS_CACHE_API, NOTIFICATION_CHANNEL_GROUPS_CACHE_API, 1568 mNotificationChannelGroupsQueryHandler); 1569 1570 /** 1571 * @hide 1572 */ invalidateNotificationChannelCache()1573 public static void invalidateNotificationChannelCache() { 1574 if (Flags.nmBinderPerfCacheChannels()) { 1575 IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, 1576 NOTIFICATION_CHANNELS_CACHE_API); 1577 } else { 1578 // if we are here, we have failed to flag something 1579 Log.wtf(TAG, "invalidateNotificationChannelCache called without flag"); 1580 } 1581 } 1582 1583 /** 1584 * @hide 1585 */ invalidateNotificationChannelGroupCache()1586 public static void invalidateNotificationChannelGroupCache() { 1587 if (Flags.nmBinderPerfCacheChannels()) { 1588 IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, 1589 NOTIFICATION_CHANNEL_GROUPS_CACHE_API); 1590 } else { 1591 // if we are here, we have failed to flag something 1592 Log.wtf(TAG, "invalidateNotificationChannelGroupCache called without flag"); 1593 } 1594 } 1595 1596 /** 1597 * For testing only: running tests with a cache requires marking the cache's property for 1598 * testing, as test APIs otherwise cannot invalidate the cache. This must be called after 1599 * calling PropertyInvalidatedCache.setTestMode(true). 1600 * @hide 1601 */ 1602 @VisibleForTesting setChannelCachesToTestMode()1603 public void setChannelCachesToTestMode() { 1604 mNotificationChannelListCache.testPropertyName(); 1605 mNotificationChannelGroupsCache.testPropertyName(); 1606 } 1607 1608 /** 1609 * @hide 1610 */ 1611 @TestApi getEffectsSuppressor()1612 public ComponentName getEffectsSuppressor() { 1613 INotificationManager service = service(); 1614 try { 1615 return service.getEffectsSuppressor(); 1616 } catch (RemoteException e) { 1617 throw e.rethrowFromSystemServer(); 1618 } 1619 } 1620 1621 /** 1622 * @hide 1623 */ matchesCallFilter(Bundle extras)1624 public boolean matchesCallFilter(Bundle extras) { 1625 INotificationManager service = service(); 1626 try { 1627 return service.matchesCallFilter(extras); 1628 } catch (RemoteException e) { 1629 throw e.rethrowFromSystemServer(); 1630 } 1631 } 1632 1633 /** 1634 * @hide 1635 */ 1636 @TestApi cleanUpCallersAfter(long timeThreshold)1637 public void cleanUpCallersAfter(long timeThreshold) { 1638 INotificationManager service = service(); 1639 try { 1640 service.cleanUpCallersAfter(timeThreshold); 1641 } catch (RemoteException e) { 1642 throw e.rethrowFromSystemServer(); 1643 } 1644 } 1645 1646 /** 1647 * @hide 1648 */ isSystemConditionProviderEnabled(String path)1649 public boolean isSystemConditionProviderEnabled(String path) { 1650 INotificationManager service = service(); 1651 try { 1652 return service.isSystemConditionProviderEnabled(path); 1653 } catch (RemoteException e) { 1654 throw e.rethrowFromSystemServer(); 1655 } 1656 } 1657 1658 /** 1659 * @hide 1660 */ 1661 @UnsupportedAppUsage setZenMode(int mode, Uri conditionId, String reason)1662 public void setZenMode(int mode, Uri conditionId, String reason) { 1663 setZenMode(mode, conditionId, reason, /* fromUser= */ false); 1664 } 1665 1666 /** @hide */ setZenMode(int mode, Uri conditionId, String reason, boolean fromUser)1667 public void setZenMode(int mode, Uri conditionId, String reason, boolean fromUser) { 1668 INotificationManager service = service(); 1669 try { 1670 service.setZenMode(mode, conditionId, reason, fromUser); 1671 } catch (RemoteException e) { 1672 throw e.rethrowFromSystemServer(); 1673 } 1674 } 1675 1676 1677 /** 1678 * @hide 1679 */ getZenMode()1680 public int getZenMode() { 1681 INotificationManager service = service(); 1682 try { 1683 return service.getZenMode(); 1684 } catch (RemoteException e) { 1685 throw e.rethrowFromSystemServer(); 1686 } 1687 } 1688 1689 /** 1690 * @hide 1691 */ 1692 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getZenModeConfig()1693 public ZenModeConfig getZenModeConfig() { 1694 INotificationManager service = service(); 1695 try { 1696 return service.getZenModeConfig(); 1697 } catch (RemoteException e) { 1698 throw e.rethrowFromSystemServer(); 1699 } 1700 } 1701 1702 /** 1703 * Returns the currently applied notification policy. 1704 * 1705 * <p> 1706 * If {@link #getCurrentInterruptionFilter} is equal to {@link #INTERRUPTION_FILTER_ALL}, 1707 * then the consolidated notification policy will match the default notification policy 1708 * returned by {@link #getNotificationPolicy}. 1709 * </p> 1710 */ getConsolidatedNotificationPolicy()1711 public @NonNull NotificationManager.Policy getConsolidatedNotificationPolicy() { 1712 INotificationManager service = service(); 1713 try { 1714 return service.getConsolidatedNotificationPolicy(); 1715 } catch (RemoteException e) { 1716 throw e.rethrowFromSystemServer(); 1717 } 1718 } 1719 1720 /** 1721 * @hide 1722 */ getRuleInstanceCount(ComponentName owner)1723 public int getRuleInstanceCount(ComponentName owner) { 1724 INotificationManager service = service(); 1725 try { 1726 return service.getRuleInstanceCount(owner); 1727 } catch (RemoteException e) { 1728 throw e.rethrowFromSystemServer(); 1729 } 1730 } 1731 1732 /** 1733 * Returns true if users can independently and fully manage {@link AutomaticZenRule} rules. This 1734 * includes the ability to independently activate/deactivate rules and overwrite/freeze the 1735 * behavior (policy) of the rule when activated. 1736 * <p> 1737 * If this method returns true, calls to 1738 * {@link #updateAutomaticZenRule(String, AutomaticZenRule)} may fail and apps should defer 1739 * rule management to system settings/uis via 1740 * {@link Settings#ACTION_AUTOMATIC_ZEN_RULE_SETTINGS}. 1741 */ areAutomaticZenRulesUserManaged()1742 public boolean areAutomaticZenRulesUserManaged() { 1743 if (Flags.modesUi()) { 1744 PackageManager pm = mContext.getPackageManager(); 1745 return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH) 1746 && !pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) 1747 && !pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); 1748 } else { 1749 return false; 1750 } 1751 } 1752 1753 /** 1754 * Returns AutomaticZenRules owned by the caller. 1755 * 1756 * <p> 1757 * Throws a SecurityException if policy access is not granted to this package. 1758 * See {@link #isNotificationPolicyAccessGranted}. 1759 */ getAutomaticZenRules()1760 public Map<String, AutomaticZenRule> getAutomaticZenRules() { 1761 INotificationManager service = service(); 1762 try { 1763 Map<String, AutomaticZenRule> result = new HashMap<>(); 1764 ParceledListSlice<AutomaticZenRule.AzrWithId> parceledRules = 1765 service.getAutomaticZenRules(); 1766 if (parceledRules != null) { 1767 for (AutomaticZenRule.AzrWithId rule : parceledRules.getList()) { 1768 result.put(rule.mId, rule.mRule); 1769 } 1770 } 1771 return result; 1772 } catch (RemoteException e) { 1773 throw e.rethrowFromSystemServer(); 1774 } 1775 } 1776 1777 /** 1778 * Returns the AutomaticZenRule with the given id, if it exists and the caller has access. 1779 * 1780 * <p> 1781 * Throws a SecurityException if policy access is not granted to this package. 1782 * See {@link #isNotificationPolicyAccessGranted}. 1783 * 1784 * <p> 1785 * Returns null if there are no zen rules that match the given id, or if the calling package 1786 * doesn't own the matching rule. See {@link AutomaticZenRule#getOwner}. 1787 */ getAutomaticZenRule(String id)1788 public AutomaticZenRule getAutomaticZenRule(String id) { 1789 INotificationManager service = service(); 1790 try { 1791 return service.getAutomaticZenRule(id); 1792 } catch (RemoteException e) { 1793 throw e.rethrowFromSystemServer(); 1794 } 1795 } 1796 1797 /** 1798 * Creates the given zen rule. 1799 * 1800 * <p> 1801 * Throws a SecurityException if policy access is not granted to this package. 1802 * See {@link #isNotificationPolicyAccessGranted}. 1803 * 1804 * @param automaticZenRule the rule to create. 1805 * @return The id of the newly created rule; null if the rule could not be created. 1806 */ addAutomaticZenRule(AutomaticZenRule automaticZenRule)1807 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) { 1808 return addAutomaticZenRule(automaticZenRule, /* fromUser= */ false); 1809 } 1810 1811 /** @hide */ 1812 @TestApi 1813 @NonNull addAutomaticZenRule(@onNull AutomaticZenRule automaticZenRule, boolean fromUser)1814 public String addAutomaticZenRule(@NonNull AutomaticZenRule automaticZenRule, 1815 boolean fromUser) { 1816 INotificationManager service = service(); 1817 try { 1818 return service.addAutomaticZenRule(automaticZenRule, 1819 mContext.getPackageName(), fromUser); 1820 } catch (RemoteException e) { 1821 throw e.rethrowFromSystemServer(); 1822 } 1823 } 1824 1825 /** 1826 * Updates the given zen rule. 1827 * 1828 * <p>Before {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, updating a rule that is not backed 1829 * up by a {@link android.service.notification.ConditionProviderService} will deactivate it if 1830 * it was previously active. Starting with {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, this 1831 * will only happen if the rule's definition is actually changing. 1832 * 1833 * <p>Throws a SecurityException if policy access is not granted to this package. 1834 * See {@link #isNotificationPolicyAccessGranted}. 1835 * 1836 * <p>Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}. 1837 * 1838 * @param id The id of the rule to update 1839 * @param automaticZenRule the rule to update. 1840 * @return Whether the rule was successfully updated. 1841 */ updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)1842 public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) { 1843 return updateAutomaticZenRule(id, automaticZenRule, /* fromUser= */ false); 1844 } 1845 1846 /** @hide */ 1847 @TestApi updateAutomaticZenRule(@onNull String id, @NonNull AutomaticZenRule automaticZenRule, boolean fromUser)1848 public boolean updateAutomaticZenRule(@NonNull String id, 1849 @NonNull AutomaticZenRule automaticZenRule, boolean fromUser) { 1850 INotificationManager service = service(); 1851 try { 1852 return service.updateAutomaticZenRule(id, automaticZenRule, fromUser); 1853 } catch (RemoteException e) { 1854 throw e.rethrowFromSystemServer(); 1855 } 1856 } 1857 1858 /** 1859 * Returns the current activation state of an {@link AutomaticZenRule}. 1860 * 1861 * <p>Returns {@link Condition#STATE_UNKNOWN} if the rule does not exist or the calling 1862 * package doesn't have access to it. 1863 * 1864 * @param id The id of the rule 1865 * @return the state of the rule. 1866 */ 1867 @Condition.State getAutomaticZenRuleState(@onNull String id)1868 public int getAutomaticZenRuleState(@NonNull String id) { 1869 INotificationManager service = service(); 1870 try { 1871 return service.getAutomaticZenRuleState(id); 1872 } catch (RemoteException e) { 1873 throw e.rethrowFromSystemServer(); 1874 } 1875 } 1876 1877 /** 1878 * Informs the notification manager that the state of an {@link AutomaticZenRule} has changed. 1879 * Use this method to put the system into Do Not Disturb mode or request that it exits Do Not 1880 * Disturb mode. The calling app must own the provided {@link android.app.AutomaticZenRule}. 1881 * 1882 * <p>This method can be used in conjunction with or as a replacement to 1883 * {@link android.service.notification.ConditionProviderService#notifyCondition(Condition)}. 1884 * 1885 * <p>The condition change may be ignored if the user has activated or deactivated the rule 1886 * manually -- the user can "override" the rule <em>this time</em>, with the rule resuming its 1887 * normal operation for the next cycle. When this has happened, the supplied condition will be 1888 * applied only once the automatic state is in agreement with the user-provided state. For 1889 * example, assume that the {@link AutomaticZenRule} corresponds to a "Driving Mode" with 1890 * automatic driving detection. 1891 * 1892 * <ol> 1893 * <li>App detects driving and notifies the system that the rule should be active, calling 1894 * this method with a {@link Condition} with {@link Condition#STATE_TRUE}). 1895 * <li>User deactivates ("snoozes") the rule for some reason. This overrides the 1896 * app-provided condition state. 1897 * <li>App is still detecting driving, so again calls with {@link Condition#STATE_TRUE}. 1898 * This is ignored by the system, as the user override prevails. 1899 * <li>Some time later, the app detects that driving stopped, so the rule should be 1900 * inactive, and calls with {@link Condition#STATE_FALSE}). This doesn't change the actual 1901 * rule state (it was already inactive due to the user's override), but clears the override. 1902 * <li>Some time later, the app detects that driving has started again, and notifies that 1903 * the rule should be active (calling with {@link Condition#STATE_TRUE} again). The rule is 1904 * activated. 1905 * </ol> 1906 * 1907 * <p>Note that the behavior at step #3 is different if the app also specifies 1908 * {@link Condition#SOURCE_USER_ACTION} as the {@link Condition#source} -- rule state updates 1909 * coming from user actions are not ignored. 1910 * 1911 * @param id The id of the rule whose state should change 1912 * @param condition The new state of this rule 1913 */ setAutomaticZenRuleState(@onNull String id, @NonNull Condition condition)1914 public void setAutomaticZenRuleState(@NonNull String id, @NonNull Condition condition) { 1915 INotificationManager service = service(); 1916 try { 1917 service.setAutomaticZenRuleState(id, condition); 1918 } catch (RemoteException e) { 1919 throw e.rethrowFromSystemServer(); 1920 } 1921 } 1922 1923 /** 1924 * Deletes the automatic zen rule with the given id. 1925 * 1926 * <p> 1927 * Throws a SecurityException if policy access is not granted to this package. 1928 * See {@link #isNotificationPolicyAccessGranted}. 1929 * 1930 * <p> 1931 * Callers can only delete rules that they own. See {@link AutomaticZenRule#getOwner}. 1932 * @param id the id of the rule to delete. 1933 * @return Whether the rule was successfully deleted. 1934 */ removeAutomaticZenRule(String id)1935 public boolean removeAutomaticZenRule(String id) { 1936 return removeAutomaticZenRule(id, /* fromUser= */ false); 1937 } 1938 1939 /** @hide */ 1940 @TestApi removeAutomaticZenRule(@onNull String id, boolean fromUser)1941 public boolean removeAutomaticZenRule(@NonNull String id, boolean fromUser) { 1942 INotificationManager service = service(); 1943 try { 1944 return service.removeAutomaticZenRule(id, fromUser); 1945 } catch (RemoteException e) { 1946 throw e.rethrowFromSystemServer(); 1947 } 1948 } 1949 1950 /** 1951 * Deletes all automatic zen rules owned by the given package. 1952 * 1953 * @hide 1954 */ removeAutomaticZenRules(String packageName)1955 public boolean removeAutomaticZenRules(String packageName) { 1956 return removeAutomaticZenRules(packageName, /* fromUser= */ false); 1957 } 1958 1959 /** @hide */ removeAutomaticZenRules(String packageName, boolean fromUser)1960 public boolean removeAutomaticZenRules(String packageName, boolean fromUser) { 1961 INotificationManager service = service(); 1962 try { 1963 return service.removeAutomaticZenRules(packageName, fromUser); 1964 } catch (RemoteException e) { 1965 throw e.rethrowFromSystemServer(); 1966 } 1967 } 1968 1969 /** 1970 * Returns the user specified importance for notifications from the calling 1971 * package. 1972 */ getImportance()1973 public @Importance int getImportance() { 1974 INotificationManager service = service(); 1975 try { 1976 return service.getPackageImportance(mContext.getPackageName()); 1977 } catch (RemoteException e) { 1978 throw e.rethrowFromSystemServer(); 1979 } 1980 } 1981 1982 /** 1983 * Returns whether notifications from the calling package are enabled. 1984 */ areNotificationsEnabled()1985 public boolean areNotificationsEnabled() { 1986 if (Flags.nmBinderPerfPermissionCheck()) { 1987 return mContext.checkSelfPermission(POST_NOTIFICATIONS) == PERMISSION_GRANTED; 1988 } else { 1989 INotificationManager service = service(); 1990 try { 1991 return service.areNotificationsEnabled(mContext.getPackageName()); 1992 } catch (RemoteException e) { 1993 throw e.rethrowFromSystemServer(); 1994 } 1995 } 1996 } 1997 1998 /** 1999 * Gets whether all notifications posted by this app can appear outside of the 2000 * notification shade, floating over other apps' content. 2001 * 2002 * <p>This value will be ignored for notifications that are posted to channels that do not 2003 * allow bubbles ({@link NotificationChannel#canBubble()}). 2004 * 2005 * @see Notification#getBubbleMetadata() 2006 * @deprecated use {@link #getBubblePreference()} instead. 2007 */ 2008 @Deprecated areBubblesAllowed()2009 public boolean areBubblesAllowed() { 2010 INotificationManager service = service(); 2011 try { 2012 return service.areBubblesAllowed(mContext.getPackageName()); 2013 } catch (RemoteException e) { 2014 throw e.rethrowFromSystemServer(); 2015 } 2016 } 2017 2018 /** 2019 * Returns whether bubbles are enabled at the feature level for the current user. When enabled, 2020 * notifications able to bubble will display an affordance allowing the user to bubble them. 2021 * 2022 * @see Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata) 2023 */ areBubblesEnabled()2024 public boolean areBubblesEnabled() { 2025 INotificationManager service = service(); 2026 try { 2027 return service.areBubblesEnabled(mContext.getUser()); 2028 } catch (RemoteException e) { 2029 throw e.rethrowFromSystemServer(); 2030 } 2031 } 2032 2033 /** 2034 * Gets the bubble preference for the app. This preference only applies to notifications that 2035 * have been properly configured to bubble. 2036 * 2037 * <p> 2038 * If {@link #BUBBLE_PREFERENCE_ALL}, then any bubble notification will appear as a bubble, as 2039 * long as the user hasn't excluded it ({@link NotificationChannel#canBubble()}). 2040 * 2041 * <p> 2042 * If {@link #BUBBLE_PREFERENCE_SELECTED}, then any bubble notification will appear as a bubble, 2043 * as long as the user has selected it. 2044 * 2045 * <p> 2046 * If {@link #BUBBLE_PREFERENCE_NONE}, then no notification may appear as a bubble from the app. 2047 * 2048 * @see Notification#getBubbleMetadata() 2049 * @return the users' bubble preference for the app. 2050 */ getBubblePreference()2051 public @BubblePreference int getBubblePreference() { 2052 INotificationManager service = service(); 2053 try { 2054 return service.getBubblePreferenceForPackage(mContext.getPackageName(), 2055 Binder.getCallingUid()); 2056 } catch (RemoteException e) { 2057 throw e.rethrowFromSystemServer(); 2058 } 2059 } 2060 2061 /** 2062 * Silences the current notification sound, if ones currently playing. 2063 * <p> 2064 * It is intended to handle use-cases such as silencing a ringing call 2065 * when the user presses the volume button during ringing. 2066 * <p> 2067 * If this method is called prior to when the notification begins playing, the sound will not be 2068 * silenced. As such it is not intended as a means to avoid playing of a sound. 2069 * @hide 2070 */ silenceNotificationSound()2071 public void silenceNotificationSound() { 2072 INotificationManager service = service(); 2073 try { 2074 service.silenceNotificationSound(); 2075 } catch (RemoteException e) { 2076 throw e.rethrowFromSystemServer(); 2077 } 2078 } 2079 2080 /** 2081 * Returns whether notifications from this package are temporarily hidden. This 2082 * could be done because the package was marked as distracting to the user via 2083 * {@code PackageManager#setDistractingPackageRestrictions(String[], int)} or because the 2084 * package is {@code PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle, 2085 * PersistableBundle, SuspendDialogInfo) suspended}. 2086 */ areNotificationsPaused()2087 public boolean areNotificationsPaused() { 2088 INotificationManager service = service(); 2089 try { 2090 return service.isPackagePaused(mContext.getPackageName()); 2091 } catch (RemoteException e) { 2092 throw e.rethrowFromSystemServer(); 2093 } 2094 } 2095 2096 /** 2097 * Checks the ability to modify Notification Policy for the calling package. 2098 * 2099 * <p> 2100 * Returns true if the calling package can modify notification policy. 2101 * 2102 * <p> 2103 * Apps can request policy access by sending the user to the activity that matches the system 2104 * intent action {@link android.provider.Settings#ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS}. 2105 * 2106 * <p> 2107 * Use {@link #ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED} to listen for 2108 * user grant or denial of this access. 2109 */ isNotificationPolicyAccessGranted()2110 public boolean isNotificationPolicyAccessGranted() { 2111 INotificationManager service = service(); 2112 try { 2113 return service.isNotificationPolicyAccessGranted(mContext.getOpPackageName()); 2114 } catch (RemoteException e) { 2115 throw e.rethrowFromSystemServer(); 2116 } 2117 } 2118 2119 /** 2120 * Checks whether the user has approved a given 2121 * {@link android.service.notification.NotificationListenerService}. 2122 * 2123 * <p> 2124 * The listener service must belong to the calling app. 2125 * 2126 * <p> 2127 * Apps can request notification listener access by sending the user to the activity that 2128 * matches the system intent action 2129 * {@link android.provider.Settings#ACTION_NOTIFICATION_LISTENER_SETTINGS}. 2130 */ isNotificationListenerAccessGranted(ComponentName listener)2131 public boolean isNotificationListenerAccessGranted(ComponentName listener) { 2132 INotificationManager service = service(); 2133 try { 2134 return service.isNotificationListenerAccessGranted(listener); 2135 } catch (RemoteException e) { 2136 throw e.rethrowFromSystemServer(); 2137 } 2138 } 2139 2140 /** 2141 * Checks whether the user has approved a given 2142 * {@link android.service.notification.NotificationAssistantService}. 2143 * 2144 * <p> 2145 * The assistant service must belong to the calling app. 2146 * 2147 * <p> 2148 * Apps can request notification assistant access by sending the user to the activity that 2149 * matches the system intent action 2150 * TODO: STOPSHIP: Add correct intent 2151 * {@link android.provider.Settings#ACTION_MANAGE_DEFAULT_APPS_SETTINGS}. 2152 * @hide 2153 */ 2154 @SystemApi isNotificationAssistantAccessGranted(@onNull ComponentName assistant)2155 public boolean isNotificationAssistantAccessGranted(@NonNull ComponentName assistant) { 2156 INotificationManager service = service(); 2157 try { 2158 return service.isNotificationAssistantAccessGranted(assistant); 2159 } catch (RemoteException e) { 2160 throw e.rethrowFromSystemServer(); 2161 } 2162 } 2163 2164 /** 2165 * Returns whether the user wants silent notifications (see {@link #IMPORTANCE_LOW} to appear 2166 * in the status bar. 2167 * 2168 * <p>Only available for {@link #isNotificationListenerAccessGranted(ComponentName) notification 2169 * listeners}. 2170 */ shouldHideSilentStatusBarIcons()2171 public boolean shouldHideSilentStatusBarIcons() { 2172 INotificationManager service = service(); 2173 try { 2174 return service.shouldHideSilentStatusIcons(mContext.getOpPackageName()); 2175 } catch (RemoteException e) { 2176 throw e.rethrowFromSystemServer(); 2177 } 2178 } 2179 2180 /** 2181 * Returns the list of {@link android.service.notification.Adjustment adjustment keys} that can 2182 * be modified by the current {@link android.service.notification.NotificationAssistantService}. 2183 * 2184 * <p>Only callable by the current 2185 * {@link android.service.notification.NotificationAssistantService}. 2186 * See {@link #isNotificationAssistantAccessGranted(ComponentName)}</p> 2187 * @hide 2188 */ 2189 @SystemApi getAllowedAssistantAdjustments()2190 public @NonNull @Adjustment.Keys List<String> getAllowedAssistantAdjustments() { 2191 INotificationManager service = service(); 2192 try { 2193 return service.getAllowedAssistantAdjustments(mContext.getOpPackageName()); 2194 } catch (RemoteException e) { 2195 throw e.rethrowFromSystemServer(); 2196 } 2197 } 2198 2199 /** 2200 * @hide 2201 */ 2202 @TestApi 2203 @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) allowAssistantAdjustment(@onNull String capability)2204 public void allowAssistantAdjustment(@NonNull String capability) { 2205 INotificationManager service = service(); 2206 try { 2207 service.allowAssistantAdjustment(capability); 2208 } catch (RemoteException e) { 2209 throw e.rethrowFromSystemServer(); 2210 } 2211 } 2212 2213 /** 2214 * @hide 2215 */ 2216 @TestApi 2217 @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) disallowAssistantAdjustment(@onNull String capability)2218 public void disallowAssistantAdjustment(@NonNull String capability) { 2219 INotificationManager service = service(); 2220 try { 2221 service.disallowAssistantAdjustment(capability); 2222 } catch (RemoteException e) { 2223 throw e.rethrowFromSystemServer(); 2224 } 2225 } 2226 2227 /** @hide */ 2228 @TestApi isNotificationPolicyAccessGrantedForPackage(@onNull String pkg)2229 public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String pkg) { 2230 INotificationManager service = service(); 2231 try { 2232 return service.isNotificationPolicyAccessGrantedForPackage(pkg); 2233 } catch (RemoteException e) { 2234 throw e.rethrowFromSystemServer(); 2235 } 2236 } 2237 2238 /** 2239 * @hide 2240 */ 2241 @TestApi 2242 @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) setAssistantAdjustmentKeyTypeState(@djustment.Types int type, boolean enabled)2243 public void setAssistantAdjustmentKeyTypeState(@Adjustment.Types int type, boolean enabled) { 2244 INotificationManager service = service(); 2245 try { 2246 service.setAssistantAdjustmentKeyTypeState(type, enabled); 2247 } catch (RemoteException e) { 2248 throw e.rethrowFromSystemServer(); 2249 } 2250 } 2251 2252 /** 2253 * @hide 2254 */ getEnabledNotificationListenerPackages()2255 public List<String> getEnabledNotificationListenerPackages() { 2256 INotificationManager service = service(); 2257 try { 2258 return service.getEnabledNotificationListenerPackages(); 2259 } catch (RemoteException e) { 2260 throw e.rethrowFromSystemServer(); 2261 } 2262 } 2263 2264 /** 2265 * Gets the current user-specified default notification policy. 2266 * 2267 * <p>For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above (with some 2268 * exceptions, such as companion device managers) this method will return the policy associated 2269 * to their implicit {@link AutomaticZenRule} instead, if it exists. See 2270 * {@link #setNotificationPolicy(Policy)}. 2271 */ getNotificationPolicy()2272 public Policy getNotificationPolicy() { 2273 INotificationManager service = service(); 2274 try { 2275 return service.getNotificationPolicy(mContext.getOpPackageName()); 2276 } catch (RemoteException e) { 2277 throw e.rethrowFromSystemServer(); 2278 } 2279 } 2280 2281 /** 2282 * Sets the current notification policy (which applies when {@link #setInterruptionFilter} is 2283 * called with the {@link #INTERRUPTION_FILTER_PRIORITY} value). 2284 * 2285 * <p>Apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above (with some 2286 * exceptions, such as companion device managers) cannot modify the global notification policy. 2287 * Calling this method will instead create or update an {@link AutomaticZenRule} associated to 2288 * the app, using a {@link ZenPolicy} corresponding to the {@link Policy} supplied here, and 2289 * which will be activated/deactivated by calls to {@link #setInterruptionFilter(int)}. 2290 * 2291 * <p>Only available if policy access is granted to this package. See 2292 * {@link #isNotificationPolicyAccessGranted}. 2293 * 2294 * @param policy The new desired policy. 2295 */ setNotificationPolicy(@onNull Policy policy)2296 public void setNotificationPolicy(@NonNull Policy policy) { 2297 setNotificationPolicy(policy, /* fromUser= */ false); 2298 } 2299 2300 /** @hide */ setNotificationPolicy(@onNull Policy policy, boolean fromUser)2301 public void setNotificationPolicy(@NonNull Policy policy, boolean fromUser) { 2302 checkRequired("policy", policy); 2303 INotificationManager service = service(); 2304 try { 2305 service.setNotificationPolicy(mContext.getOpPackageName(), policy, fromUser); 2306 } catch (RemoteException e) { 2307 throw e.rethrowFromSystemServer(); 2308 } 2309 } 2310 2311 /** @hide */ setNotificationPolicyAccessGranted(String pkg, boolean granted)2312 public void setNotificationPolicyAccessGranted(String pkg, boolean granted) { 2313 INotificationManager service = service(); 2314 try { 2315 service.setNotificationPolicyAccessGranted(pkg, granted); 2316 } catch (RemoteException e) { 2317 throw e.rethrowFromSystemServer(); 2318 } 2319 } 2320 2321 /** @hide */ setNotificationListenerAccessGranted( @onNull ComponentName listener, boolean granted)2322 public void setNotificationListenerAccessGranted( 2323 @NonNull ComponentName listener, boolean granted) { 2324 setNotificationListenerAccessGranted(listener, granted, true); 2325 } 2326 /** 2327 * Gets the device-default notification policy as a ZenPolicy. 2328 * @hide 2329 */ 2330 @TestApi getDefaultZenPolicy()2331 public @NonNull ZenPolicy getDefaultZenPolicy() { 2332 INotificationManager service = service(); 2333 try { 2334 return service.getDefaultZenPolicy(); 2335 } catch (RemoteException e) { 2336 throw e.rethrowFromSystemServer(); 2337 } 2338 } 2339 /** 2340 * @hide 2341 */ 2342 @FlaggedApi(Flags.FLAG_MODES_UI) setManualZenRuleDeviceEffects(@onNull ZenDeviceEffects effects)2343 public void setManualZenRuleDeviceEffects(@NonNull ZenDeviceEffects effects) { 2344 INotificationManager service = service(); 2345 try { 2346 service.setManualZenRuleDeviceEffects(effects); 2347 } catch (RemoteException e) { 2348 throw e.rethrowFromSystemServer(); 2349 } 2350 } 2351 2352 /** 2353 * For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above, the 2354 * {@code setNotificationListenerAccessGranted} method will use the user contained within the 2355 * context. 2356 * For apps targeting an SDK version <em>below</em> this, the user of the calling process will 2357 * be used (Process.myUserHandle()). 2358 * 2359 * @hide 2360 */ 2361 @ChangeId 2362 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 2363 public static final long SET_LISTENER_ACCESS_GRANTED_IS_USER_AWARE = 302563478L; 2364 2365 /** 2366 * Grants/revokes Notification Listener access to the given component for current user. 2367 * To grant access for a particular user, obtain this service by using the {@link Context} 2368 * provided by {@link Context#createPackageContextAsUser} 2369 * 2370 * @param listener Name of component to grant/revoke access 2371 * @param granted Grant/revoke access 2372 * @param userSet Whether the action was triggered explicitly by user 2373 * @hide 2374 */ 2375 @SystemApi 2376 @TestApi 2377 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 2378 @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) setNotificationListenerAccessGranted( @onNull ComponentName listener, boolean granted, boolean userSet)2379 public void setNotificationListenerAccessGranted( 2380 @NonNull ComponentName listener, boolean granted, boolean userSet) { 2381 INotificationManager service = service(); 2382 try { 2383 if (CompatChanges.isChangeEnabled(SET_LISTENER_ACCESS_GRANTED_IS_USER_AWARE)) { 2384 service.setNotificationListenerAccessGrantedForUser(listener, mContext.getUserId(), 2385 granted, userSet); 2386 } else { 2387 service.setNotificationListenerAccessGranted(listener, granted, userSet); 2388 } 2389 } catch (RemoteException e) { 2390 throw e.rethrowFromSystemServer(); 2391 } 2392 } 2393 2394 /** @hide */ setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId, boolean granted)2395 public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId, 2396 boolean granted) { 2397 INotificationManager service = service(); 2398 try { 2399 service.setNotificationListenerAccessGrantedForUser(listener, userId, granted, true); 2400 } catch (RemoteException e) { 2401 throw e.rethrowFromSystemServer(); 2402 } 2403 } 2404 2405 /** 2406 * Grants/revokes Notification Assistant access to {@code assistant} for current user. 2407 * To grant access for a particular user, obtain this service by using the {@link Context} 2408 * provided by {@link Context#createPackageContextAsUser} 2409 * 2410 * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to 2411 * current assistant 2412 * @param granted Grant/revoke access 2413 * @hide 2414 */ 2415 @SystemApi setNotificationAssistantAccessGranted(@ullable ComponentName assistant, boolean granted)2416 public void setNotificationAssistantAccessGranted(@Nullable ComponentName assistant, 2417 boolean granted) { 2418 INotificationManager service = service(); 2419 try { 2420 service.setNotificationAssistantAccessGranted(assistant, granted); 2421 } catch (RemoteException e) { 2422 throw e.rethrowFromSystemServer(); 2423 } 2424 } 2425 2426 /** 2427 * Gets the list of enabled notification listener components for current user. 2428 * To query for a particular user, obtain this service by using the {@link Context} 2429 * provided by {@link Context#createPackageContextAsUser} 2430 * 2431 * @return the list of {@link ComponentName}s of the notification listeners 2432 * @hide 2433 */ 2434 @SystemApi 2435 @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) getEnabledNotificationListeners()2436 public @NonNull List<ComponentName> getEnabledNotificationListeners() { 2437 return getEnabledNotificationListeners(mContext.getUserId()); 2438 } 2439 2440 /** @hide */ getEnabledNotificationListeners(int userId)2441 public List<ComponentName> getEnabledNotificationListeners(int userId) { 2442 INotificationManager service = service(); 2443 try { 2444 return service.getEnabledNotificationListeners(userId); 2445 } catch (RemoteException e) { 2446 throw e.rethrowFromSystemServer(); 2447 } 2448 } 2449 2450 /** @hide */ 2451 @SystemApi getAllowedNotificationAssistant()2452 public @Nullable ComponentName getAllowedNotificationAssistant() { 2453 INotificationManager service = service(); 2454 try { 2455 return service.getAllowedNotificationAssistant(); 2456 } catch (RemoteException e) { 2457 throw e.rethrowFromSystemServer(); 2458 } 2459 } 2460 2461 /** 2462 * Whether the given user has an enabled 2463 * {@link android.service.notification.NotificationListenerService} with the given package name. 2464 * 2465 * @param packageName the package name of the NotificationListenerService class 2466 * @param userHandle the handle of the user that set the listener 2467 * @hide 2468 */ 2469 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 2470 @SuppressLint("UserHandle") hasEnabledNotificationListener(@onNull String packageName, @NonNull UserHandle userHandle)2471 public boolean hasEnabledNotificationListener(@NonNull String packageName, 2472 @NonNull UserHandle userHandle) { 2473 INotificationManager service = service(); 2474 try { 2475 return service.hasEnabledNotificationListener(packageName, userHandle.getIdentifier()); 2476 } catch (RemoteException e) { 2477 throw e.rethrowFromSystemServer(); 2478 } 2479 } checkRequired(String name, Object value)2480 private static void checkRequired(String name, Object value) { 2481 if (value == null) { 2482 throw new IllegalArgumentException(name + " is required"); 2483 } 2484 } 2485 2486 /** 2487 * Controls whether toast rate limiting is enabled for the calling uid. 2488 * 2489 * @param enable true to enable toast rate limiting, false to disable it 2490 * @hide 2491 */ 2492 @TestApi 2493 @RequiresPermission(android.Manifest.permission.MANAGE_TOAST_RATE_LIMITING) setToastRateLimitingEnabled(boolean enable)2494 public void setToastRateLimitingEnabled(boolean enable) { 2495 INotificationManager service = service(); 2496 try { 2497 service.setToastRateLimitingEnabled(enable); 2498 } catch (RemoteException e) { 2499 throw e.rethrowFromSystemServer(); 2500 } 2501 } 2502 2503 /** 2504 * Notification policy configuration. Represents user-preferences for notification 2505 * filtering. 2506 */ 2507 public static class Policy implements android.os.Parcelable { 2508 /** Reminder notifications are prioritized. */ 2509 public static final int PRIORITY_CATEGORY_REMINDERS = 1 << 0; 2510 /** Event notifications are prioritized. */ 2511 public static final int PRIORITY_CATEGORY_EVENTS = 1 << 1; 2512 /** Message notifications are prioritized. */ 2513 public static final int PRIORITY_CATEGORY_MESSAGES = 1 << 2; 2514 /** Calls are prioritized. */ 2515 public static final int PRIORITY_CATEGORY_CALLS = 1 << 3; 2516 /** Calls from repeat callers are prioritized. */ 2517 public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 1 << 4; 2518 /** Alarms are prioritized */ 2519 public static final int PRIORITY_CATEGORY_ALARMS = 1 << 5; 2520 /** Media, game, voice navigation are prioritized */ 2521 public static final int PRIORITY_CATEGORY_MEDIA = 1 << 6; 2522 /**System (catch-all for non-never suppressible sounds) are prioritized */ 2523 public static final int PRIORITY_CATEGORY_SYSTEM = 1 << 7; 2524 /** 2525 * Conversations are allowed through DND. 2526 */ 2527 public static final int PRIORITY_CATEGORY_CONVERSATIONS = 1 << 8; 2528 2529 /** 2530 * @hide 2531 */ 2532 public static final int[] ALL_PRIORITY_CATEGORIES = { 2533 PRIORITY_CATEGORY_ALARMS, 2534 PRIORITY_CATEGORY_MEDIA, 2535 PRIORITY_CATEGORY_SYSTEM, 2536 PRIORITY_CATEGORY_REMINDERS, 2537 PRIORITY_CATEGORY_EVENTS, 2538 PRIORITY_CATEGORY_MESSAGES, 2539 PRIORITY_CATEGORY_CALLS, 2540 PRIORITY_CATEGORY_REPEAT_CALLERS, 2541 PRIORITY_CATEGORY_CONVERSATIONS, 2542 }; 2543 2544 /** @hide */ 2545 @IntDef(prefix = { "PRIORITY_SENDERS_" }, value = { 2546 PRIORITY_SENDERS_ANY, 2547 PRIORITY_SENDERS_CONTACTS, 2548 PRIORITY_SENDERS_STARRED, 2549 }) 2550 @Retention(RetentionPolicy.SOURCE) 2551 public @interface PrioritySenders {} 2552 2553 /** Any sender is prioritized. */ 2554 public static final int PRIORITY_SENDERS_ANY = 0; 2555 /** Saved contacts are prioritized. */ 2556 public static final int PRIORITY_SENDERS_CONTACTS = 1; 2557 /** Only starred contacts are prioritized. */ 2558 public static final int PRIORITY_SENDERS_STARRED = 2; 2559 2560 2561 /** @hide */ 2562 @IntDef(prefix = { "CONVERSATION_SENDERS_" }, value = { 2563 CONVERSATION_SENDERS_ANYONE, 2564 CONVERSATION_SENDERS_IMPORTANT, 2565 CONVERSATION_SENDERS_NONE, 2566 }) 2567 @Retention(RetentionPolicy.SOURCE) 2568 public @interface ConversationSenders {} 2569 /** 2570 * Used to indicate all conversations can bypass dnd. 2571 */ 2572 public static final int CONVERSATION_SENDERS_ANYONE = ZenPolicy.CONVERSATION_SENDERS_ANYONE; 2573 2574 /** 2575 * Used to indicate important conversations can bypass dnd. 2576 */ 2577 public static final int CONVERSATION_SENDERS_IMPORTANT = 2578 ZenPolicy.CONVERSATION_SENDERS_IMPORTANT; 2579 2580 /** 2581 * Used to indicate no conversations can bypass dnd. 2582 */ 2583 public static final int CONVERSATION_SENDERS_NONE = ZenPolicy.CONVERSATION_SENDERS_NONE; 2584 2585 /** Notification categories to prioritize. Bitmask of PRIORITY_CATEGORY_* constants. */ 2586 public final int priorityCategories; 2587 2588 /** Notification senders to prioritize for calls. One of: 2589 * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */ 2590 @PrioritySenders 2591 public final int priorityCallSenders; 2592 2593 /** Notification senders to prioritize for messages. One of: 2594 * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */ 2595 @PrioritySenders 2596 public final int priorityMessageSenders; 2597 2598 /** 2599 * Notification senders to prioritize for conversations. One of: 2600 * {@link #CONVERSATION_SENDERS_NONE}, {@link #CONVERSATION_SENDERS_IMPORTANT}, 2601 * {@link #CONVERSATION_SENDERS_ANYONE}. 2602 */ 2603 @ConversationSenders 2604 public final int priorityConversationSenders; 2605 2606 /** 2607 * @hide 2608 */ 2609 public static final int CONVERSATION_SENDERS_UNSET = -1; 2610 2611 /** 2612 * @hide 2613 */ 2614 public static final int SUPPRESSED_EFFECTS_UNSET = -1; 2615 2616 /** 2617 * Whether notifications suppressed by DND should not interrupt visually (e.g. with 2618 * notification lights or by turning the screen on) when the screen is off. 2619 * 2620 * @deprecated use {@link #SUPPRESSED_EFFECT_FULL_SCREEN_INTENT} and 2621 * {@link #SUPPRESSED_EFFECT_AMBIENT} and {@link #SUPPRESSED_EFFECT_LIGHTS} individually. 2622 */ 2623 @Deprecated 2624 public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0; 2625 /** 2626 * Whether notifications suppressed by DND should not interrupt visually when the screen 2627 * is on (e.g. by peeking onto the screen). 2628 * 2629 * @deprecated use {@link #SUPPRESSED_EFFECT_PEEK}. 2630 */ 2631 @Deprecated 2632 public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1; 2633 2634 /** 2635 * Whether {@link Notification#fullScreenIntent full screen intents} from 2636 * notifications intercepted by DND are blocked. 2637 */ 2638 public static final int SUPPRESSED_EFFECT_FULL_SCREEN_INTENT = 1 << 2; 2639 2640 /** 2641 * Whether {@link NotificationChannel#shouldShowLights() notification lights} from 2642 * notifications intercepted by DND are blocked. 2643 */ 2644 public static final int SUPPRESSED_EFFECT_LIGHTS = 1 << 3; 2645 2646 /** 2647 * Whether notifications intercepted by DND are prevented from peeking. 2648 */ 2649 public static final int SUPPRESSED_EFFECT_PEEK = 1 << 4; 2650 2651 /** 2652 * Whether notifications intercepted by DND are prevented from appearing in the status bar, 2653 * on devices that support status bars. 2654 */ 2655 public static final int SUPPRESSED_EFFECT_STATUS_BAR = 1 << 5; 2656 2657 /** 2658 * Whether {@link NotificationChannel#canShowBadge() badges} from 2659 * notifications intercepted by DND are blocked on devices that support badging. 2660 */ 2661 public static final int SUPPRESSED_EFFECT_BADGE = 1 << 6; 2662 2663 /** 2664 * Whether notification intercepted by DND are prevented from appearing on ambient displays 2665 * on devices that support ambient display. 2666 */ 2667 public static final int SUPPRESSED_EFFECT_AMBIENT = 1 << 7; 2668 2669 /** 2670 * Whether notification intercepted by DND are prevented from appearing in notification 2671 * list views like the notification shade or lockscreen on devices that support those 2672 * views. 2673 */ 2674 public static final int SUPPRESSED_EFFECT_NOTIFICATION_LIST = 1 << 8; 2675 2676 private static final int[] ALL_SUPPRESSED_EFFECTS = { 2677 SUPPRESSED_EFFECT_SCREEN_OFF, 2678 SUPPRESSED_EFFECT_SCREEN_ON, 2679 SUPPRESSED_EFFECT_FULL_SCREEN_INTENT, 2680 SUPPRESSED_EFFECT_LIGHTS, 2681 SUPPRESSED_EFFECT_PEEK, 2682 SUPPRESSED_EFFECT_STATUS_BAR, 2683 SUPPRESSED_EFFECT_BADGE, 2684 SUPPRESSED_EFFECT_AMBIENT, 2685 SUPPRESSED_EFFECT_NOTIFICATION_LIST 2686 }; 2687 2688 /** 2689 * Visual effects to suppress for a notification that is filtered by Do Not Disturb mode. 2690 * Bitmask of SUPPRESSED_EFFECT_* constants. 2691 */ 2692 public final int suppressedVisualEffects; 2693 2694 /** 2695 * @hide 2696 */ 2697 public static final int STATE_HAS_PRIORITY_CHANNELS = 1 << 0; 2698 2699 /** 2700 * Whether the policy indicates that even priority channels are NOT permitted to bypass DND. 2701 * Note that this state explicitly marks the "disallow" state because the default behavior 2702 * is to allow priority channels to break through. 2703 * @hide 2704 */ 2705 public static final int STATE_PRIORITY_CHANNELS_BLOCKED = 1 << 1; 2706 2707 /** 2708 * @hide 2709 */ 2710 public static final int STATE_UNSET = -1; 2711 2712 /** 2713 * Notification state information that is necessary to determine Do Not Disturb behavior. 2714 * Bitmask of STATE_* constants. 2715 * @hide 2716 */ 2717 public final int state; 2718 2719 /** 2720 * Constructs a policy for Do Not Disturb priority mode behavior. 2721 * 2722 * <p> 2723 * Apps that target API levels below {@link Build.VERSION_CODES#P} cannot 2724 * change user-designated values to allow or disallow 2725 * {@link Policy#PRIORITY_CATEGORY_ALARMS}, {@link Policy#PRIORITY_CATEGORY_SYSTEM}, and 2726 * {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd. 2727 * 2728 * @param priorityCategories bitmask of categories of notifications that can bypass DND. 2729 * @param priorityCallSenders which callers can bypass DND. 2730 * @param priorityMessageSenders which message senders can bypass DND. 2731 */ Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders)2732 public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) { 2733 this(priorityCategories, priorityCallSenders, priorityMessageSenders, 2734 SUPPRESSED_EFFECTS_UNSET, STATE_UNSET, CONVERSATION_SENDERS_UNSET); 2735 } 2736 2737 /** 2738 * Constructs a policy for Do Not Disturb priority mode behavior. 2739 * 2740 * <p> 2741 * Apps that target API levels below {@link Build.VERSION_CODES#R} cannot 2742 * change user-designated values to allow or disallow 2743 * {@link Policy#PRIORITY_CATEGORY_CONVERSATIONS}, from bypassing dnd. 2744 * <p> 2745 * Additionally, apps that target API levels below {@link Build.VERSION_CODES#P} can 2746 * only modify the {@link #SUPPRESSED_EFFECT_SCREEN_ON} and 2747 * {@link #SUPPRESSED_EFFECT_SCREEN_OFF} bits of the suppressed visual effects field. 2748 * All other suppressed effects will be ignored and reconstituted from the screen on 2749 * and screen off values. 2750 * <p> 2751 * Apps that target {@link Build.VERSION_CODES#P} or above can set any 2752 * suppressed visual effects. However, if any suppressed effects > 2753 * {@link #SUPPRESSED_EFFECT_SCREEN_ON} are set, {@link #SUPPRESSED_EFFECT_SCREEN_ON} 2754 * and {@link #SUPPRESSED_EFFECT_SCREEN_OFF} will be ignored and reconstituted from 2755 * the more specific suppressed visual effect bits. Apps should migrate to targeting 2756 * specific effects instead of the deprecated {@link #SUPPRESSED_EFFECT_SCREEN_ON} and 2757 * {@link #SUPPRESSED_EFFECT_SCREEN_OFF} effects. 2758 * 2759 * @param priorityCategories bitmask of categories of notifications that can bypass DND. 2760 * @param priorityCallSenders which callers can bypass DND. 2761 * @param priorityMessageSenders which message senders can bypass DND. 2762 * @param suppressedVisualEffects which visual interruptions should be suppressed from 2763 * notifications that are filtered by DND. 2764 */ Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders, int suppressedVisualEffects)2765 public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders, 2766 int suppressedVisualEffects) { 2767 this(priorityCategories, priorityCallSenders, priorityMessageSenders, 2768 suppressedVisualEffects, STATE_UNSET, CONVERSATION_SENDERS_UNSET); 2769 } 2770 2771 /** 2772 * Constructs a policy for Do Not Disturb priority mode behavior. 2773 * 2774 * <p> 2775 * Apps that target API levels below {@link Build.VERSION_CODES#P} cannot 2776 * change user-designated values to allow or disallow 2777 * {@link Policy#PRIORITY_CATEGORY_CONVERSATIONS} from bypassing dnd. If you do need 2778 * to change them, use a {@link ZenPolicy} associated with an {@link AutomaticZenRule} 2779 * instead of changing the global setting. 2780 * <p> 2781 * Apps that target API levels below {@link Build.VERSION_CODES#P} cannot 2782 * change user-designated values to allow or disallow 2783 * {@link Policy#PRIORITY_CATEGORY_ALARMS}, 2784 * {@link Policy#PRIORITY_CATEGORY_SYSTEM}, and 2785 * {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd. 2786 * <p> 2787 * Additionally, apps that target API levels below {@link Build.VERSION_CODES#P} can 2788 * only modify the {@link #SUPPRESSED_EFFECT_SCREEN_ON} and 2789 * {@link #SUPPRESSED_EFFECT_SCREEN_OFF} bits of the suppressed visual effects field. 2790 * All other suppressed effects will be ignored and reconstituted from the screen on 2791 * and screen off values. 2792 * <p> 2793 * Apps that target {@link Build.VERSION_CODES#P} or above can set any 2794 * suppressed visual effects. However, if any suppressed effects > 2795 * {@link #SUPPRESSED_EFFECT_SCREEN_ON} are set, {@link #SUPPRESSED_EFFECT_SCREEN_ON} 2796 * and {@link #SUPPRESSED_EFFECT_SCREEN_OFF} will be ignored and reconstituted from 2797 * the more specific suppressed visual effect bits. Apps should migrate to targeting 2798 * specific effects instead of the deprecated {@link #SUPPRESSED_EFFECT_SCREEN_ON} and 2799 * {@link #SUPPRESSED_EFFECT_SCREEN_OFF} effects. 2800 * 2801 * @param priorityCategories bitmask of categories of notifications that can bypass DND. 2802 * @param priorityCallSenders which callers can bypass DND. 2803 * @param priorityMessageSenders which message senders can bypass DND. 2804 * @param suppressedVisualEffects which visual interruptions should be suppressed from 2805 * notifications that are filtered by DND. 2806 */ Policy(int priorityCategories, @PrioritySenders int priorityCallSenders, @PrioritySenders int priorityMessageSenders, int suppressedVisualEffects, @ConversationSenders int priorityConversationSenders)2807 public Policy(int priorityCategories, @PrioritySenders int priorityCallSenders, 2808 @PrioritySenders int priorityMessageSenders, 2809 int suppressedVisualEffects, @ConversationSenders int priorityConversationSenders) { 2810 this(priorityCategories, priorityCallSenders, priorityMessageSenders, 2811 suppressedVisualEffects, STATE_UNSET, priorityConversationSenders); 2812 } 2813 2814 /** @hide */ Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders, int suppressedVisualEffects, int state, int priorityConversationSenders)2815 public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders, 2816 int suppressedVisualEffects, int state, int priorityConversationSenders) { 2817 this.priorityCategories = priorityCategories; 2818 this.priorityCallSenders = priorityCallSenders; 2819 this.priorityMessageSenders = priorityMessageSenders; 2820 this.suppressedVisualEffects = suppressedVisualEffects; 2821 this.state = state; 2822 this.priorityConversationSenders = priorityConversationSenders; 2823 } 2824 2825 2826 /** @hide */ Policy(Parcel source)2827 public Policy(Parcel source) { 2828 this(source.readInt(), source.readInt(), source.readInt(), source.readInt(), 2829 source.readInt(), source.readInt()); 2830 } 2831 2832 @Override writeToParcel(Parcel dest, int flags)2833 public void writeToParcel(Parcel dest, int flags) { 2834 dest.writeInt(priorityCategories); 2835 dest.writeInt(priorityCallSenders); 2836 dest.writeInt(priorityMessageSenders); 2837 dest.writeInt(suppressedVisualEffects); 2838 dest.writeInt(state); 2839 dest.writeInt(priorityConversationSenders); 2840 } 2841 2842 @Override describeContents()2843 public int describeContents() { 2844 return 0; 2845 } 2846 2847 @Override hashCode()2848 public int hashCode() { 2849 return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders, 2850 suppressedVisualEffects, state, priorityConversationSenders); 2851 } 2852 2853 @Override equals(@ullable Object o)2854 public boolean equals(@Nullable Object o) { 2855 if (!(o instanceof Policy)) return false; 2856 if (o == this) return true; 2857 final Policy other = (Policy) o; 2858 return other.priorityCategories == priorityCategories 2859 && other.priorityCallSenders == priorityCallSenders 2860 && other.priorityMessageSenders == priorityMessageSenders 2861 && suppressedVisualEffectsEqual(suppressedVisualEffects, 2862 other.suppressedVisualEffects) 2863 && other.state == this.state 2864 && other.priorityConversationSenders == this.priorityConversationSenders; 2865 } 2866 suppressedVisualEffectsEqual(int suppressedEffects, int otherSuppressedVisualEffects)2867 private boolean suppressedVisualEffectsEqual(int suppressedEffects, 2868 int otherSuppressedVisualEffects) { 2869 if (suppressedEffects == otherSuppressedVisualEffects) { 2870 return true; 2871 } 2872 2873 if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) { 2874 suppressedEffects |= SUPPRESSED_EFFECT_PEEK; 2875 } 2876 if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) { 2877 suppressedEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 2878 suppressedEffects |= SUPPRESSED_EFFECT_LIGHTS; 2879 suppressedEffects |= SUPPRESSED_EFFECT_AMBIENT; 2880 } 2881 2882 if ((otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) { 2883 otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK; 2884 } 2885 if ((otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) { 2886 otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 2887 otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS; 2888 otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT; 2889 } 2890 2891 if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_ON) 2892 != (otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON)) { 2893 int currSuppressedEffects = (suppressedEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0 2894 ? otherSuppressedVisualEffects : suppressedEffects; 2895 if ((currSuppressedEffects & SUPPRESSED_EFFECT_PEEK) == 0) { 2896 return false; 2897 } 2898 } 2899 2900 if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_OFF) 2901 != (otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF)) { 2902 int currSuppressedEffects = (suppressedEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0 2903 ? otherSuppressedVisualEffects : suppressedEffects; 2904 if ((currSuppressedEffects & SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) == 0 2905 || (currSuppressedEffects & SUPPRESSED_EFFECT_LIGHTS) == 0 2906 || (currSuppressedEffects & SUPPRESSED_EFFECT_AMBIENT) == 0) { 2907 return false; 2908 } 2909 } 2910 2911 int thisWithoutOldEffects = suppressedEffects 2912 & ~SUPPRESSED_EFFECT_SCREEN_ON 2913 & ~SUPPRESSED_EFFECT_SCREEN_OFF; 2914 int otherWithoutOldEffects = otherSuppressedVisualEffects 2915 & ~SUPPRESSED_EFFECT_SCREEN_ON 2916 & ~SUPPRESSED_EFFECT_SCREEN_OFF; 2917 return thisWithoutOldEffects == otherWithoutOldEffects; 2918 } 2919 2920 @Override toString()2921 public String toString() { 2922 return new StringBuilder().append("NotificationManager.Policy[") 2923 .append("priorityCategories=") 2924 .append(priorityCategoriesToString(priorityCategories)) 2925 .append(",priorityCallSenders=") 2926 .append(prioritySendersToString(priorityCallSenders)) 2927 .append(",priorityMessageSenders=") 2928 .append(prioritySendersToString(priorityMessageSenders)) 2929 .append(",priorityConvSenders=") 2930 .append(conversationSendersToString(priorityConversationSenders)) 2931 .append(",suppressedVisualEffects=") 2932 .append(suppressedEffectsToString(suppressedVisualEffects)) 2933 .append(",hasPriorityChannels=") 2934 .append((state == STATE_UNSET 2935 ? "unset" 2936 : ((state & STATE_HAS_PRIORITY_CHANNELS) != 0) 2937 ? "true" 2938 : "false")) 2939 .append(",allowPriorityChannels=") 2940 .append((state == STATE_UNSET 2941 ? "unset" 2942 : (allowPriorityChannels() ? "true" : "false"))) 2943 .append("]") 2944 .toString(); 2945 } 2946 2947 /** @hide */ dumpDebug(ProtoOutputStream proto, long fieldId)2948 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 2949 final long pToken = proto.start(fieldId); 2950 2951 bitwiseToProtoEnum(proto, PolicyProto.PRIORITY_CATEGORIES, priorityCategories); 2952 proto.write(PolicyProto.PRIORITY_CALL_SENDER, priorityCallSenders); 2953 proto.write(PolicyProto.PRIORITY_MESSAGE_SENDER, priorityMessageSenders); 2954 bitwiseToProtoEnum( 2955 proto, PolicyProto.SUPPRESSED_VISUAL_EFFECTS, suppressedVisualEffects); 2956 2957 proto.end(pToken); 2958 } 2959 bitwiseToProtoEnum(ProtoOutputStream proto, long fieldId, int data)2960 private static void bitwiseToProtoEnum(ProtoOutputStream proto, long fieldId, int data) { 2961 for (int i = 1; data > 0; ++i, data >>>= 1) { 2962 if ((data & 1) == 1) { 2963 proto.write(fieldId, i); 2964 } 2965 } 2966 } 2967 2968 /** 2969 * @hide 2970 */ getAllSuppressedVisualEffects()2971 public static int getAllSuppressedVisualEffects() { 2972 int effects = 0; 2973 for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) { 2974 effects |= ALL_SUPPRESSED_EFFECTS[i]; 2975 } 2976 return effects; 2977 } 2978 2979 /** 2980 * @hide 2981 */ areAllVisualEffectsSuppressed(int effects)2982 public static boolean areAllVisualEffectsSuppressed(int effects) { 2983 for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) { 2984 final int effect = ALL_SUPPRESSED_EFFECTS[i]; 2985 if ((effects & effect) == 0) { 2986 return false; 2987 } 2988 } 2989 return true; 2990 } 2991 toggleEffects(int currentEffects, int[] effects, boolean suppress)2992 private static int toggleEffects(int currentEffects, int[] effects, boolean suppress) { 2993 for (int i = 0; i < effects.length; i++) { 2994 final int effect = effects[i]; 2995 if (suppress) { 2996 currentEffects |= effect; 2997 } else { 2998 currentEffects &= ~effect; 2999 } 3000 } 3001 return currentEffects; 3002 } 3003 suppressedEffectsToString(int effects)3004 public static String suppressedEffectsToString(int effects) { 3005 if (effects <= 0) return ""; 3006 final StringBuilder sb = new StringBuilder(); 3007 for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) { 3008 final int effect = ALL_SUPPRESSED_EFFECTS[i]; 3009 if ((effects & effect) != 0) { 3010 if (sb.length() > 0) sb.append(','); 3011 sb.append(effectToString(effect)); 3012 } 3013 effects &= ~effect; 3014 } 3015 if (effects != 0) { 3016 if (sb.length() > 0) sb.append(','); 3017 sb.append("UNKNOWN_").append(effects); 3018 } 3019 return sb.toString(); 3020 } 3021 priorityCategoriesToString(int priorityCategories)3022 public static String priorityCategoriesToString(int priorityCategories) { 3023 if (priorityCategories == 0) return ""; 3024 final StringBuilder sb = new StringBuilder(); 3025 for (int i = 0; i < ALL_PRIORITY_CATEGORIES.length; i++) { 3026 final int priorityCategory = ALL_PRIORITY_CATEGORIES[i]; 3027 if ((priorityCategories & priorityCategory) != 0) { 3028 if (sb.length() > 0) sb.append(','); 3029 sb.append(priorityCategoryToString(priorityCategory)); 3030 } 3031 priorityCategories &= ~priorityCategory; 3032 } 3033 if (priorityCategories != 0) { 3034 if (sb.length() > 0) sb.append(','); 3035 sb.append("PRIORITY_CATEGORY_UNKNOWN_").append(priorityCategories); 3036 } 3037 return sb.toString(); 3038 } 3039 effectToString(int effect)3040 private static String effectToString(int effect) { 3041 switch (effect) { 3042 case SUPPRESSED_EFFECT_FULL_SCREEN_INTENT: 3043 return "SUPPRESSED_EFFECT_FULL_SCREEN_INTENT"; 3044 case SUPPRESSED_EFFECT_LIGHTS: 3045 return "SUPPRESSED_EFFECT_LIGHTS"; 3046 case SUPPRESSED_EFFECT_PEEK: 3047 return "SUPPRESSED_EFFECT_PEEK"; 3048 case SUPPRESSED_EFFECT_STATUS_BAR: 3049 return "SUPPRESSED_EFFECT_STATUS_BAR"; 3050 case SUPPRESSED_EFFECT_BADGE: 3051 return "SUPPRESSED_EFFECT_BADGE"; 3052 case SUPPRESSED_EFFECT_AMBIENT: 3053 return "SUPPRESSED_EFFECT_AMBIENT"; 3054 case SUPPRESSED_EFFECT_NOTIFICATION_LIST: 3055 return "SUPPRESSED_EFFECT_NOTIFICATION_LIST"; 3056 case SUPPRESSED_EFFECT_SCREEN_OFF: 3057 return "SUPPRESSED_EFFECT_SCREEN_OFF"; 3058 case SUPPRESSED_EFFECT_SCREEN_ON: 3059 return "SUPPRESSED_EFFECT_SCREEN_ON"; 3060 case SUPPRESSED_EFFECTS_UNSET: 3061 return "SUPPRESSED_EFFECTS_UNSET"; 3062 default: return "UNKNOWN_" + effect; 3063 } 3064 } 3065 priorityCategoryToString(int priorityCategory)3066 private static String priorityCategoryToString(int priorityCategory) { 3067 switch (priorityCategory) { 3068 case PRIORITY_CATEGORY_REMINDERS: return "PRIORITY_CATEGORY_REMINDERS"; 3069 case PRIORITY_CATEGORY_EVENTS: return "PRIORITY_CATEGORY_EVENTS"; 3070 case PRIORITY_CATEGORY_MESSAGES: return "PRIORITY_CATEGORY_MESSAGES"; 3071 case PRIORITY_CATEGORY_CALLS: return "PRIORITY_CATEGORY_CALLS"; 3072 case PRIORITY_CATEGORY_REPEAT_CALLERS: return "PRIORITY_CATEGORY_REPEAT_CALLERS"; 3073 case PRIORITY_CATEGORY_ALARMS: return "PRIORITY_CATEGORY_ALARMS"; 3074 case PRIORITY_CATEGORY_MEDIA: return "PRIORITY_CATEGORY_MEDIA"; 3075 case PRIORITY_CATEGORY_SYSTEM: return "PRIORITY_CATEGORY_SYSTEM"; 3076 case PRIORITY_CATEGORY_CONVERSATIONS: return "PRIORITY_CATEGORY_CONVERSATIONS"; 3077 default: return "PRIORITY_CATEGORY_UNKNOWN_" + priorityCategory; 3078 } 3079 } 3080 prioritySendersToString(int prioritySenders)3081 public static String prioritySendersToString(int prioritySenders) { 3082 switch (prioritySenders) { 3083 case PRIORITY_SENDERS_ANY: return "PRIORITY_SENDERS_ANY"; 3084 case PRIORITY_SENDERS_CONTACTS: return "PRIORITY_SENDERS_CONTACTS"; 3085 case PRIORITY_SENDERS_STARRED: return "PRIORITY_SENDERS_STARRED"; 3086 default: return "PRIORITY_SENDERS_UNKNOWN_" + prioritySenders; 3087 } 3088 } 3089 3090 /** 3091 * @hide 3092 */ conversationSendersToString(int priorityConversationSenders)3093 public static @NonNull String conversationSendersToString(int priorityConversationSenders) { 3094 switch (priorityConversationSenders) { 3095 case CONVERSATION_SENDERS_ANYONE: 3096 return "anyone"; 3097 case CONVERSATION_SENDERS_IMPORTANT: 3098 return "important"; 3099 case CONVERSATION_SENDERS_NONE: 3100 return "none"; 3101 case CONVERSATION_SENDERS_UNSET: 3102 return "unset"; 3103 } 3104 return "invalidConversationType{" + priorityConversationSenders + "}"; 3105 } 3106 3107 public static final @android.annotation.NonNull Parcelable.Creator<Policy> CREATOR 3108 = new Parcelable.Creator<Policy>() { 3109 @Override 3110 public Policy createFromParcel(Parcel in) { 3111 return new Policy(in); 3112 } 3113 3114 @Override 3115 public Policy[] newArray(int size) { 3116 return new Policy[size]; 3117 } 3118 }; 3119 3120 /** @hide **/ allowAlarms()3121 public boolean allowAlarms() { 3122 return (priorityCategories & PRIORITY_CATEGORY_ALARMS) != 0; 3123 } 3124 3125 /** @hide **/ allowMedia()3126 public boolean allowMedia() { 3127 return (priorityCategories & PRIORITY_CATEGORY_MEDIA) != 0; 3128 } 3129 3130 /** @hide **/ allowSystem()3131 public boolean allowSystem() { 3132 return (priorityCategories & PRIORITY_CATEGORY_SYSTEM) != 0; 3133 } 3134 3135 /** @hide **/ allowRepeatCallers()3136 public boolean allowRepeatCallers() { 3137 return (priorityCategories & PRIORITY_CATEGORY_REPEAT_CALLERS) != 0; 3138 } 3139 3140 /** @hide **/ allowCalls()3141 public boolean allowCalls() { 3142 return (priorityCategories & PRIORITY_CATEGORY_CALLS) != 0; 3143 } 3144 3145 /** @hide **/ allowConversations()3146 public boolean allowConversations() { 3147 return (priorityCategories & PRIORITY_CATEGORY_CONVERSATIONS) != 0; 3148 } 3149 3150 /** @hide **/ allowMessages()3151 public boolean allowMessages() { 3152 return (priorityCategories & PRIORITY_CATEGORY_MESSAGES) != 0; 3153 } 3154 3155 /** @hide **/ allowEvents()3156 public boolean allowEvents() { 3157 return (priorityCategories & PRIORITY_CATEGORY_EVENTS) != 0; 3158 } 3159 3160 /** @hide **/ allowReminders()3161 public boolean allowReminders() { 3162 return (priorityCategories & PRIORITY_CATEGORY_REMINDERS) != 0; 3163 } 3164 3165 /** @hide **/ 3166 @PrioritySenders allowCallsFrom()3167 public int allowCallsFrom() { 3168 return priorityCallSenders; 3169 } 3170 3171 /** @hide **/ 3172 @PrioritySenders allowMessagesFrom()3173 public int allowMessagesFrom() { 3174 return priorityMessageSenders; 3175 } 3176 3177 /** @hide **/ 3178 @ConversationSenders allowConversationsFrom()3179 public int allowConversationsFrom() { 3180 return priorityConversationSenders; 3181 } 3182 3183 /** @hide **/ showFullScreenIntents()3184 public boolean showFullScreenIntents() { 3185 return (suppressedVisualEffects & SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) == 0; 3186 } 3187 3188 /** @hide **/ showLights()3189 public boolean showLights() { 3190 return (suppressedVisualEffects & SUPPRESSED_EFFECT_LIGHTS) == 0; 3191 } 3192 3193 /** @hide **/ showPeeking()3194 public boolean showPeeking() { 3195 return (suppressedVisualEffects & SUPPRESSED_EFFECT_PEEK) == 0; 3196 } 3197 3198 /** @hide **/ showStatusBarIcons()3199 public boolean showStatusBarIcons() { 3200 return (suppressedVisualEffects & SUPPRESSED_EFFECT_STATUS_BAR) == 0; 3201 } 3202 3203 /** @hide **/ showAmbient()3204 public boolean showAmbient() { 3205 return (suppressedVisualEffects & SUPPRESSED_EFFECT_AMBIENT) == 0; 3206 } 3207 3208 /** @hide **/ showBadges()3209 public boolean showBadges() { 3210 return (suppressedVisualEffects & SUPPRESSED_EFFECT_BADGE) == 0; 3211 } 3212 3213 /** @hide **/ showInNotificationList()3214 public boolean showInNotificationList() { 3215 return (suppressedVisualEffects & SUPPRESSED_EFFECT_NOTIFICATION_LIST) == 0; 3216 } 3217 3218 /** @hide **/ 3219 @TestApi // so CTS tests can read this state without having to use implementation detail allowPriorityChannels()3220 public boolean allowPriorityChannels() { 3221 if (state == STATE_UNSET) { 3222 return true; // default 3223 } 3224 return (state & STATE_PRIORITY_CHANNELS_BLOCKED) == 0; 3225 } 3226 3227 /** @hide */ hasPriorityChannels()3228 public boolean hasPriorityChannels() { 3229 return (state & STATE_HAS_PRIORITY_CHANNELS) != 0; 3230 } 3231 3232 /** @hide **/ policyState(boolean hasPriorityChannels, boolean allowPriorityChannels)3233 public static int policyState(boolean hasPriorityChannels, boolean allowPriorityChannels) { 3234 int state = 0; 3235 if (hasPriorityChannels) { 3236 state |= STATE_HAS_PRIORITY_CHANNELS; 3237 } 3238 if (!allowPriorityChannels) { 3239 state |= STATE_PRIORITY_CHANNELS_BLOCKED; 3240 } 3241 return state; 3242 } 3243 3244 /** 3245 * returns a deep copy of this policy 3246 * @hide 3247 */ copy()3248 public Policy copy() { 3249 final Parcel parcel = Parcel.obtain(); 3250 try { 3251 writeToParcel(parcel, 0); 3252 parcel.setDataPosition(0); 3253 return new Policy(parcel); 3254 } finally { 3255 parcel.recycle(); 3256 } 3257 } 3258 } 3259 3260 /** 3261 * Recover a list of active notifications: ones that have been posted by the calling app that 3262 * have not yet been dismissed by the user or {@link #cancel(String, int)}ed by the app. 3263 * 3264 * <p><Each notification is embedded in a {@link StatusBarNotification} object, including the 3265 * original <code>tag</code> and <code>id</code> supplied to 3266 * {@link #notify(String, int, Notification) notify()} 3267 * (via {@link StatusBarNotification#getTag() getTag()} and 3268 * {@link StatusBarNotification#getId() getId()}) as well as a copy of the original 3269 * {@link Notification} object (via {@link StatusBarNotification#getNotification()}). 3270 * </p> 3271 * <p>From {@link Build.VERSION_CODES#Q}, will also return notifications you've posted as an 3272 * app's notification delegate via 3273 * {@link NotificationManager#notifyAsPackage(String, String, int, Notification)}. 3274 * </p> 3275 * 3276 * @return An array of {@link StatusBarNotification}. 3277 */ getActiveNotifications()3278 public StatusBarNotification[] getActiveNotifications() { 3279 final INotificationManager service = service(); 3280 final String pkg = mContext.getPackageName(); 3281 try { 3282 final ParceledListSlice<StatusBarNotification> parceledList 3283 = service.getAppActiveNotifications(pkg, mContext.getUserId()); 3284 if (parceledList != null) { 3285 final List<StatusBarNotification> list = parceledList.getList(); 3286 return list.toArray(new StatusBarNotification[list.size()]); 3287 } 3288 } catch (RemoteException e) { 3289 throw e.rethrowFromSystemServer(); 3290 } 3291 return new StatusBarNotification[0]; 3292 } 3293 3294 /** 3295 * Gets the current notification interruption filter. 3296 * <p> 3297 * The interruption filter defines which notifications are allowed to 3298 * interrupt the user (e.g. via sound & vibration) and is applied 3299 * globally. 3300 */ getCurrentInterruptionFilter()3301 public final @InterruptionFilter int getCurrentInterruptionFilter() { 3302 final INotificationManager service = service(); 3303 try { 3304 return zenModeToInterruptionFilter(service.getZenMode()); 3305 } catch (RemoteException e) { 3306 throw e.rethrowFromSystemServer(); 3307 } 3308 } 3309 3310 /** 3311 * Sets the current notification interruption filter. 3312 * <p> 3313 * The interruption filter defines which notifications are allowed to 3314 * interrupt the user (e.g. via sound & vibration) and is applied 3315 * globally. 3316 * 3317 * <p>Apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above (with some 3318 * exceptions, such as companion device managers) cannot modify the global interruption filter. 3319 * Calling this method will instead activate or deactivate an {@link AutomaticZenRule} 3320 * associated to the app, using a {@link ZenPolicy} that corresponds to the {@link Policy} 3321 * supplied to {@link #setNotificationPolicy(Policy)} (or the global policy when one wasn't 3322 * provided). 3323 * 3324 * <p> Only available if policy access is granted to this package. See 3325 * {@link #isNotificationPolicyAccessGranted}. 3326 */ setInterruptionFilter(@nterruptionFilter int interruptionFilter)3327 public final void setInterruptionFilter(@InterruptionFilter int interruptionFilter) { 3328 setInterruptionFilter(interruptionFilter, /* fromUser= */ false); 3329 } 3330 3331 /** @hide */ setInterruptionFilter(@nterruptionFilter int interruptionFilter, boolean fromUser)3332 public final void setInterruptionFilter(@InterruptionFilter int interruptionFilter, 3333 boolean fromUser) { 3334 final INotificationManager service = service(); 3335 try { 3336 service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter, 3337 fromUser); 3338 } catch (RemoteException e) { 3339 throw e.rethrowFromSystemServer(); 3340 } 3341 } 3342 3343 /** 3344 * Returns whether a call from the provided URI is permitted to notify the user. 3345 * <p> 3346 * A true return value indicates one of the following: Do Not Disturb is not currently active; 3347 * or the caller is a repeat caller and the current policy allows interruptions from repeat 3348 * callers; or the caller is in the user's set of contacts whose calls are allowed to interrupt 3349 * Do Not Disturb. 3350 * </p> 3351 * <p> 3352 * If Do Not Disturb is enabled and either no interruptions or only alarms are allowed, this 3353 * method will return false regardless of input. 3354 * </p> 3355 * <p> 3356 * The provided URI should be a <code>tel:</code> or <code>mailto:</code> schema URI indicating 3357 * the source of the call. For an accurate answer regarding whether the caller matches the 3358 * user's permitted contacts, the path part of the URI must match an entry the Contacts database 3359 * in the appropriate column. 3360 * </p> 3361 * <p> 3362 * Passing in a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} is also 3363 * permissible, but should only be used for priority contact interruptions and may not provide 3364 * accurate results in the case of repeat callers. 3365 * </p> 3366 * <p> 3367 * See also {@link Person.Builder#setUri} and 3368 * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} 3369 * for more information. 3370 * </p> 3371 * <p> 3372 * Callers of this method must have notification listener access, permission to read contacts, 3373 * or have system permissions. 3374 * </p> 3375 * <p> 3376 * NOTE: This method calls into Contacts, which may take some time, and should not be called 3377 * on the main thread. 3378 * </p> 3379 * 3380 * @param uri A URI representing a caller. Must not be null. 3381 * @return A boolean indicating whether a call from the URI provided would be allowed to 3382 * interrupt the user given the current filter. 3383 */ 3384 @WorkerThread matchesCallFilter(@onNull Uri uri)3385 public boolean matchesCallFilter(@NonNull Uri uri) { 3386 Bundle extras = new Bundle(); 3387 ArrayList<Person> pList = new ArrayList<>(); 3388 pList.add(new Person.Builder().setUri(uri.toString()).build()); 3389 extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, pList); 3390 3391 return matchesCallFilter(extras); 3392 } 3393 3394 /** @hide */ zenModeToInterruptionFilter(int zen)3395 public static int zenModeToInterruptionFilter(int zen) { 3396 switch (zen) { 3397 case Global.ZEN_MODE_OFF: return INTERRUPTION_FILTER_ALL; 3398 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return INTERRUPTION_FILTER_PRIORITY; 3399 case Global.ZEN_MODE_ALARMS: return INTERRUPTION_FILTER_ALARMS; 3400 case Global.ZEN_MODE_NO_INTERRUPTIONS: return INTERRUPTION_FILTER_NONE; 3401 default: return INTERRUPTION_FILTER_UNKNOWN; 3402 } 3403 } 3404 3405 /** @hide */ zenModeFromInterruptionFilter(int interruptionFilter, int defValue)3406 public static int zenModeFromInterruptionFilter(int interruptionFilter, int defValue) { 3407 switch (interruptionFilter) { 3408 case INTERRUPTION_FILTER_ALL: return Global.ZEN_MODE_OFF; 3409 case INTERRUPTION_FILTER_PRIORITY: return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 3410 case INTERRUPTION_FILTER_ALARMS: return Global.ZEN_MODE_ALARMS; 3411 case INTERRUPTION_FILTER_NONE: return Global.ZEN_MODE_NO_INTERRUPTIONS; 3412 default: return defValue; 3413 } 3414 } 3415 3416 /** 3417 * Callback to receive updates when a call notification has been posted or removed 3418 * @hide 3419 */ 3420 @SystemApi 3421 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) 3422 public interface CallNotificationEventListener { 3423 /** 3424 * Called when a call notification was posted by a package this listener 3425 * has registered for. 3426 * @param packageName package name of the app that posted the removed notification 3427 */ 3428 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) onCallNotificationPosted(@onNull String packageName, @NonNull UserHandle userHandle)3429 void onCallNotificationPosted(@NonNull String packageName, @NonNull UserHandle userHandle); 3430 3431 /** 3432 * Called when a call notification was removed by a package this listener 3433 * has registered for. 3434 * @param packageName package name of the app that removed notification 3435 */ 3436 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) onCallNotificationRemoved(@onNull String packageName, @NonNull UserHandle userHandle)3437 void onCallNotificationRemoved(@NonNull String packageName, @NonNull UserHandle userHandle); 3438 } 3439 3440 private static class CallNotificationEventCallbackStub extends 3441 ICallNotificationEventCallback.Stub { 3442 final String mPackageName; 3443 final UserHandle mUserHandle; 3444 final Executor mExecutor; 3445 final CallNotificationEventListener mListener; 3446 CallNotificationEventCallbackStub(@onNull String packageName, @NonNull UserHandle userHandle, @NonNull @CallbackExecutor Executor executor, @NonNull CallNotificationEventListener listener)3447 CallNotificationEventCallbackStub(@NonNull String packageName, 3448 @NonNull UserHandle userHandle, @NonNull @CallbackExecutor Executor executor, 3449 @NonNull CallNotificationEventListener listener) { 3450 mPackageName = packageName; 3451 mUserHandle = userHandle; 3452 mExecutor = executor; 3453 mListener = listener; 3454 } 3455 3456 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) 3457 @Override onCallNotificationPosted(String packageName, UserHandle userHandle)3458 public void onCallNotificationPosted(String packageName, UserHandle userHandle) { 3459 mExecutor.execute(() -> mListener.onCallNotificationPosted(packageName, userHandle)); 3460 } 3461 3462 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) 3463 @Override onCallNotificationRemoved(String packageName, UserHandle userHandle)3464 public void onCallNotificationRemoved(String packageName, UserHandle userHandle) { 3465 mExecutor.execute(() -> mListener.onCallNotificationRemoved(packageName, userHandle)); 3466 } 3467 } 3468 3469 /** 3470 * Register a listener to be notified when a call notification is posted or removed 3471 * for a specific package and user. 3472 * 3473 * @param packageName Which package to monitor 3474 * @param userHandle Which user to monitor 3475 * @param executor Callback will run on this executor 3476 * @param listener Listener to register 3477 * @hide 3478 */ 3479 @SystemApi 3480 @RequiresPermission(allOf = { 3481 android.Manifest.permission.INTERACT_ACROSS_USERS, 3482 android.Manifest.permission.ACCESS_NOTIFICATIONS}) 3483 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) 3484 @SuppressLint("UserHandle") registerCallNotificationEventListener(@onNull String packageName, @NonNull UserHandle userHandle, @NonNull @CallbackExecutor Executor executor, @NonNull CallNotificationEventListener listener)3485 public void registerCallNotificationEventListener(@NonNull String packageName, 3486 @NonNull UserHandle userHandle, @NonNull @CallbackExecutor Executor executor, 3487 @NonNull CallNotificationEventListener listener) { 3488 checkRequired("packageName", packageName); 3489 checkRequired("userHandle", userHandle); 3490 checkRequired("executor", executor); 3491 checkRequired("listener", listener); 3492 INotificationManager service = service(); 3493 try { 3494 synchronized (mCallNotificationEventCallbacks) { 3495 CallNotificationEventCallbackStub callbackStub = 3496 new CallNotificationEventCallbackStub(packageName, userHandle, 3497 executor, listener); 3498 mCallNotificationEventCallbacks.put(listener, callbackStub); 3499 3500 service.registerCallNotificationEventListener(packageName, userHandle, 3501 callbackStub); 3502 } 3503 } catch (RemoteException e) { 3504 throw e.rethrowFromSystemServer(); 3505 } 3506 } 3507 3508 /** 3509 * Unregister a listener that was previously 3510 * registered with {@link #registerCallNotificationEventListener} 3511 * 3512 * @param listener Listener to unregister 3513 * @hide 3514 */ 3515 @SystemApi 3516 @FlaggedApi(android.service.notification.Flags.FLAG_CALLSTYLE_CALLBACK_API) 3517 @RequiresPermission(allOf = { 3518 android.Manifest.permission.INTERACT_ACROSS_USERS, 3519 android.Manifest.permission.ACCESS_NOTIFICATIONS}) unregisterCallNotificationEventListener( @onNull CallNotificationEventListener listener)3520 public void unregisterCallNotificationEventListener( 3521 @NonNull CallNotificationEventListener listener) { 3522 checkRequired("listener", listener); 3523 INotificationManager service = service(); 3524 try { 3525 synchronized (mCallNotificationEventCallbacks) { 3526 CallNotificationEventCallbackStub callbackStub = 3527 mCallNotificationEventCallbacks.remove(listener); 3528 if (callbackStub != null) { 3529 service.unregisterCallNotificationEventListener(callbackStub.mPackageName, 3530 callbackStub.mUserHandle, callbackStub); 3531 } 3532 } 3533 } catch (RemoteException e) { 3534 throw e.rethrowFromSystemServer(); 3535 } 3536 } 3537 3538 /** 3539 * Returns the list of {@link Adjustment} keys that the current approved 3540 * {@link android.service.notification.NotificationAssistantService} does not support. 3541 * @hide 3542 */ 3543 @TestApi 3544 @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) getUnsupportedAdjustmentTypes()3545 public @NonNull Set<String> getUnsupportedAdjustmentTypes() { 3546 INotificationManager service = service(); 3547 try { 3548 return new HashSet<>(service.getUnsupportedAdjustmentTypes()); 3549 } catch (RemoteException e) { 3550 throw e.rethrowFromSystemServer(); 3551 } 3552 } 3553 } 3554