1 /* 2 * Copyright (C) 2015 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.app.ActivityOptions.BackgroundActivityStartMode; 20 21 import android.annotation.IntDef; 22 import android.annotation.IntRange; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SystemApi; 27 import android.annotation.TestApi; 28 import android.app.compat.CompatChanges; 29 import android.compat.annotation.ChangeId; 30 import android.compat.annotation.Disabled; 31 import android.compat.annotation.EnabledSince; 32 import android.content.BroadcastReceiver; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.os.Build; 36 import android.os.Bundle; 37 import android.os.BundleMerger; 38 import android.os.PowerExemptionManager; 39 import android.os.PowerExemptionManager.ReasonCode; 40 import android.os.PowerExemptionManager.TempAllowListType; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.Objects; 45 46 /** 47 * Helper class for building an options Bundle that can be used with 48 * {@link android.content.Context#sendBroadcast(android.content.Intent) 49 * Context.sendBroadcast(Intent)} and related methods. 50 */ 51 @android.ravenwood.annotation.RavenwoodKeepWholeClass 52 public class BroadcastOptions extends ComponentOptions { 53 private @Flags int mFlags; 54 private long mTemporaryAppAllowlistDuration; 55 private @TempAllowListType int mTemporaryAppAllowlistType; 56 private @ReasonCode int mTemporaryAppAllowlistReasonCode; 57 private @Nullable String mTemporaryAppAllowlistReason; 58 private int mMinManifestReceiverApiLevel = 0; 59 private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT; 60 private String[] mRequireAllOfPermissions; 61 private String[] mRequireNoneOfPermissions; 62 private long mRequireCompatChangeId = CHANGE_INVALID; 63 private long mIdForResponseEvent; 64 private @DeliveryGroupPolicy int mDeliveryGroupPolicy; 65 private @Nullable String mDeliveryGroupMatchingNamespaceFragment; 66 private @Nullable String mDeliveryGroupMatchingKeyFragment; 67 private @Nullable BundleMerger mDeliveryGroupExtrasMerger; 68 private @Nullable IntentFilter mDeliveryGroupMatchingFilter; 69 private @DeferralPolicy int mDeferralPolicy; 70 71 /** @hide */ 72 @IntDef(flag = true, prefix = { "FLAG_" }, value = { 73 FLAG_DONT_SEND_TO_RESTRICTED_APPS, 74 FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS, 75 FLAG_REQUIRE_COMPAT_CHANGE_ENABLED, 76 FLAG_IS_ALARM_BROADCAST, 77 FLAG_SHARE_IDENTITY, 78 FLAG_INTERACTIVE, 79 }) 80 @Retention(RetentionPolicy.SOURCE) 81 public @interface Flags {} 82 83 private static final int FLAG_DONT_SEND_TO_RESTRICTED_APPS = 1 << 0; 84 private static final int FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1 << 1; 85 private static final int FLAG_REQUIRE_COMPAT_CHANGE_ENABLED = 1 << 2; 86 private static final int FLAG_IS_ALARM_BROADCAST = 1 << 3; 87 private static final int FLAG_SHARE_IDENTITY = 1 << 4; 88 private static final int FLAG_INTERACTIVE = 1 << 5; 89 90 /** 91 * Change ID which is invalid. 92 * 93 * @hide 94 */ 95 public static final long CHANGE_INVALID = Long.MIN_VALUE; 96 97 /** 98 * Change ID which is always enabled, for testing purposes. 99 * 100 * @hide 101 */ 102 @TestApi 103 @ChangeId 104 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.BASE) 105 public static final long CHANGE_ALWAYS_ENABLED = 209888056L; 106 107 /** 108 * Change ID which is always disabled, for testing purposes. 109 * 110 * @hide 111 */ 112 @TestApi 113 @ChangeId 114 @Disabled 115 public static final long CHANGE_ALWAYS_DISABLED = 210856463L; 116 117 /** 118 * Corresponds to {@link #mFlags}. 119 */ 120 private static final String KEY_FLAGS = "android:broadcast.flags"; 121 122 /** 123 * How long to temporarily put an app on the power allowlist when executing this broadcast 124 * to it. 125 */ 126 private static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION 127 = "android:broadcast.temporaryAppAllowlistDuration"; 128 129 private static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE 130 = "android:broadcast.temporaryAppAllowlistType"; 131 132 private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE = 133 "android:broadcast.temporaryAppAllowlistReasonCode"; 134 135 private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON = 136 "android:broadcast.temporaryAppAllowlistReason"; 137 138 /** 139 * Corresponds to {@link #setMinManifestReceiverApiLevel}. 140 */ 141 private static final String KEY_MIN_MANIFEST_RECEIVER_API_LEVEL 142 = "android:broadcast.minManifestReceiverApiLevel"; 143 144 /** 145 * Corresponds to {@link #setMaxManifestReceiverApiLevel}. 146 */ 147 private static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL 148 = "android:broadcast.maxManifestReceiverApiLevel"; 149 150 /** 151 * Corresponds to {@link #setRequireAllOfPermissions} 152 * @hide 153 */ 154 public static final String KEY_REQUIRE_ALL_OF_PERMISSIONS = 155 "android:broadcast.requireAllOfPermissions"; 156 157 /** 158 * Corresponds to {@link #setRequireNoneOfPermissions} 159 * @hide 160 */ 161 public static final String KEY_REQUIRE_NONE_OF_PERMISSIONS = 162 "android:broadcast.requireNoneOfPermissions"; 163 164 /** 165 * Corresponds to {@link #setRequireCompatChange(long, boolean)} 166 */ 167 private static final String KEY_REQUIRE_COMPAT_CHANGE_ID = 168 "android:broadcast.requireCompatChangeId"; 169 170 /** 171 * @hide 172 * @deprecated Use {@link android.os.PowerExemptionManager# 173 * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED} instead. 174 */ 175 @Deprecated 176 public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 177 PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 178 179 /** 180 * @hide 181 * @deprecated Use {@link android.os.PowerExemptionManager# 182 * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} instead. 183 */ 184 @Deprecated 185 public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 186 PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; 187 188 /** 189 * Corresponds to {@link #recordResponseEventWhileInBackground(long)}. 190 */ 191 private static final String KEY_ID_FOR_RESPONSE_EVENT = 192 "android:broadcast.idForResponseEvent"; 193 194 /** 195 * Corresponds to {@link #setDeliveryGroupPolicy(int)}. 196 */ 197 private static final String KEY_DELIVERY_GROUP_POLICY = 198 "android:broadcast.deliveryGroupPolicy"; 199 200 /** 201 * Corresponds to namespace fragment of {@link #setDeliveryGroupMatchingKey(String, String)}. 202 */ 203 private static final String KEY_DELIVERY_GROUP_NAMESPACE = 204 "android:broadcast.deliveryGroupMatchingNamespace"; 205 206 /** 207 * Corresponds to key fragment of {@link #setDeliveryGroupMatchingKey(String, String)}. 208 */ 209 private static final String KEY_DELIVERY_GROUP_KEY = 210 "android:broadcast.deliveryGroupMatchingKey"; 211 212 /** 213 * Corresponds to {@link #setDeliveryGroupExtrasMerger(BundleMerger)}. 214 */ 215 private static final String KEY_DELIVERY_GROUP_EXTRAS_MERGER = 216 "android:broadcast.deliveryGroupExtrasMerger"; 217 218 /** 219 * Corresponds to {@link #setDeliveryGroupMatchingFilter(IntentFilter)}. 220 */ 221 private static final String KEY_DELIVERY_GROUP_MATCHING_FILTER = 222 "android:broadcast.deliveryGroupMatchingFilter"; 223 224 /** 225 * Corresponds to {@link #setDeferralPolicy(int)} 226 */ 227 private static final String KEY_DEFERRAL_POLICY = 228 "android:broadcast.deferralPolicy"; 229 230 /** 231 * The list of delivery group policies which specify how multiple broadcasts belonging to 232 * the same delivery group has to be handled. 233 * @hide 234 */ 235 @IntDef(prefix = { "DELIVERY_GROUP_POLICY_" }, value = { 236 DELIVERY_GROUP_POLICY_ALL, 237 DELIVERY_GROUP_POLICY_MOST_RECENT, 238 DELIVERY_GROUP_POLICY_MERGED, 239 }) 240 @Retention(RetentionPolicy.SOURCE) 241 public @interface DeliveryGroupPolicy {} 242 243 /** 244 * Delivery group policy that indicates that all the broadcasts in the delivery group 245 * need to be delivered as is. 246 */ 247 public static final int DELIVERY_GROUP_POLICY_ALL = 0; 248 249 /** 250 * Delivery group policy that indicates that only the most recent broadcast in the delivery 251 * group need to be delivered and the rest can be dropped. 252 */ 253 public static final int DELIVERY_GROUP_POLICY_MOST_RECENT = 1; 254 255 /** 256 * Delivery group policy that indicates that the extras data from the broadcasts in the 257 * delivery group need to be merged into a single broadcast and the rest can be dropped. 258 * 259 * @hide 260 */ 261 public static final int DELIVERY_GROUP_POLICY_MERGED = 2; 262 263 /** {@hide} */ 264 @IntDef(prefix = { "DEFERRAL_POLICY_" }, value = { 265 DEFERRAL_POLICY_DEFAULT, 266 DEFERRAL_POLICY_NONE, 267 DEFERRAL_POLICY_UNTIL_ACTIVE, 268 }) 269 @Retention(RetentionPolicy.SOURCE) 270 public @interface DeferralPolicy {} 271 272 /** 273 * Deferral policy that indicates no desire has been expressed, and that the 274 * system should use a reasonable default behavior. 275 */ 276 public static final int DEFERRAL_POLICY_DEFAULT = 0; 277 278 /** 279 * Deferral policy that indicates a strong desire that no receiver of this 280 * broadcast should be deferred. 281 */ 282 public static final int DEFERRAL_POLICY_NONE = 1; 283 284 /** 285 * Deferral policy that indicates a strong desire that each receiver of this 286 * broadcast should be deferred until that receiver's process is in an 287 * active (non-cached) state. Whether an app's process state is considered 288 * active is independent of its standby bucket. 289 * <p> 290 * This policy only applies to runtime registered receivers of a broadcast, 291 * and does not apply to ordered broadcasts, alarm broadcasts, interactive 292 * broadcasts, or manifest broadcasts. 293 * <p> 294 * This policy means that a runtime registered receiver will not typically 295 * execute until that receiver's process is brought to an active state by 296 * some other action, such as a job, alarm, or service binding. As a result, 297 * the receiver may be delayed indefinitely. 298 * <p> 299 * When this policy is set on an unordered broadcast with a completion 300 * callback, the completion callback will run once all eligible processes 301 * have finished receiving the broadcast. Processes in inactive process 302 * state are not considered eligible and may not receive the broadcast prior 303 * to the completion callback. 304 */ 305 public static final int DEFERRAL_POLICY_UNTIL_ACTIVE = 2; 306 307 /** 308 * Creates a basic {@link BroadcastOptions} with no options initially set. 309 * 310 * @return an instance of {@code BroadcastOptions} against which options can be set 311 */ makeBasic()312 public static @NonNull BroadcastOptions makeBasic() { 313 BroadcastOptions opts = new BroadcastOptions(); 314 return opts; 315 } 316 317 /** @hide */ 318 @TestApi BroadcastOptions()319 public BroadcastOptions() { 320 super(); 321 resetTemporaryAppAllowlist(); 322 } 323 324 /** @hide */ 325 @TestApi BroadcastOptions(@onNull Bundle opts)326 public BroadcastOptions(@NonNull Bundle opts) { 327 super(opts); 328 // Match the logic in toBundle(). 329 mFlags = opts.getInt(KEY_FLAGS, 0); 330 if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) { 331 mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION); 332 mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE); 333 mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, 334 PowerExemptionManager.REASON_UNKNOWN); 335 mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON); 336 } else { 337 resetTemporaryAppAllowlist(); 338 } 339 mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0); 340 mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, 341 Build.VERSION_CODES.CUR_DEVELOPMENT); 342 mRequireAllOfPermissions = opts.getStringArray(KEY_REQUIRE_ALL_OF_PERMISSIONS); 343 mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS); 344 mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID); 345 mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT); 346 mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY, 347 DELIVERY_GROUP_POLICY_ALL); 348 mDeliveryGroupMatchingNamespaceFragment = opts.getString(KEY_DELIVERY_GROUP_NAMESPACE); 349 mDeliveryGroupMatchingKeyFragment = opts.getString(KEY_DELIVERY_GROUP_KEY); 350 mDeliveryGroupExtrasMerger = opts.getParcelable(KEY_DELIVERY_GROUP_EXTRAS_MERGER, 351 BundleMerger.class); 352 mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, 353 IntentFilter.class); 354 mDeferralPolicy = opts.getInt(KEY_DEFERRAL_POLICY, DEFERRAL_POLICY_DEFAULT); 355 } 356 357 /** @hide */ 358 @NonNull makeWithDeferUntilActive(boolean deferUntilActive)359 public static BroadcastOptions makeWithDeferUntilActive(boolean deferUntilActive) { 360 final BroadcastOptions opts = BroadcastOptions.makeBasic(); 361 if (deferUntilActive) { 362 opts.setDeferralPolicy(DEFERRAL_POLICY_UNTIL_ACTIVE); 363 } 364 return opts; 365 } 366 367 /** 368 * Set a duration for which the system should temporary place an application on the 369 * power allowlist when this broadcast is being delivered to it. 370 * @param duration The duration in milliseconds; 0 means to not place on allowlist. 371 * @deprecated use {@link #setTemporaryAppAllowlist(long, int, int, String)} instead. 372 * @hide 373 */ 374 @Deprecated 375 @SystemApi 376 @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, 377 android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, 378 android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) setTemporaryAppWhitelistDuration(long duration)379 public void setTemporaryAppWhitelistDuration(long duration) { 380 setTemporaryAppAllowlist(duration, 381 PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 382 PowerExemptionManager.REASON_UNKNOWN, null); 383 } 384 385 /** 386 * Set a duration for which the system should temporary place an application on the 387 * power allowlist when this broadcast is being delivered to it, specify the temp allowlist 388 * type. 389 * @hide 390 * 391 * @param duration the duration in milliseconds. 392 * 0 means to not place on allowlist, and clears previous call to this method. 393 * @param type one of {@link TempAllowListType}. 394 * {@link PowerExemptionManager#TEMPORARY_ALLOW_LIST_TYPE_NONE} means 395 * to not place on allowlist, and clears previous call to this method. 396 * @param reasonCode one of {@link ReasonCode}, use 397 * {@link PowerExemptionManager#REASON_UNKNOWN} if not sure. 398 * @param reason A human-readable reason explaining why the app is temp allowlisted. Only 399 * used for logging purposes. Could be null or empty string. 400 */ 401 @SystemApi 402 @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, 403 android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, 404 android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) setTemporaryAppAllowlist(long duration, @TempAllowListType int type, @ReasonCode int reasonCode, @Nullable String reason)405 public void setTemporaryAppAllowlist(long duration, @TempAllowListType int type, 406 @ReasonCode int reasonCode, @Nullable String reason) { 407 mTemporaryAppAllowlistDuration = duration; 408 mTemporaryAppAllowlistType = type; 409 mTemporaryAppAllowlistReasonCode = reasonCode; 410 mTemporaryAppAllowlistReason = reason; 411 412 if (!isTemporaryAppAllowlistSet()) { 413 resetTemporaryAppAllowlist(); 414 } 415 } 416 isTemporaryAppAllowlistSet()417 private boolean isTemporaryAppAllowlistSet() { 418 return mTemporaryAppAllowlistDuration > 0 419 && mTemporaryAppAllowlistType 420 != PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE; 421 } 422 resetTemporaryAppAllowlist()423 private void resetTemporaryAppAllowlist() { 424 mTemporaryAppAllowlistDuration = 0; 425 mTemporaryAppAllowlistType = PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE; 426 mTemporaryAppAllowlistReasonCode = PowerExemptionManager.REASON_UNKNOWN; 427 mTemporaryAppAllowlistReason = null; 428 } 429 430 /** 431 * Return {@link #setTemporaryAppAllowlist}. 432 * @hide 433 */ 434 @TestApi getTemporaryAppAllowlistDuration()435 public long getTemporaryAppAllowlistDuration() { 436 return mTemporaryAppAllowlistDuration; 437 } 438 439 /** 440 * Return {@link #mTemporaryAppAllowlistType}. 441 * @hide 442 */ 443 @TestApi getTemporaryAppAllowlistType()444 public @TempAllowListType int getTemporaryAppAllowlistType() { 445 return mTemporaryAppAllowlistType; 446 } 447 448 /** 449 * Return {@link #mTemporaryAppAllowlistReasonCode}. 450 * @hide 451 */ 452 @TestApi getTemporaryAppAllowlistReasonCode()453 public @ReasonCode int getTemporaryAppAllowlistReasonCode() { 454 return mTemporaryAppAllowlistReasonCode; 455 } 456 457 /** 458 * Return {@link #mTemporaryAppAllowlistReason}. 459 * @hide 460 */ 461 @TestApi getTemporaryAppAllowlistReason()462 public @Nullable String getTemporaryAppAllowlistReason() { 463 return mTemporaryAppAllowlistReason; 464 } 465 466 /** 467 * Set the minimum target API level of receivers of the broadcast. If an application 468 * is targeting an API level less than this, the broadcast will not be delivered to 469 * them. This only applies to receivers declared in the app's AndroidManifest.xml. 470 * 471 * @deprecated to give developers the most flexibility during beta releases, 472 * we strongly encourage using {@link ChangeId} instead of 473 * target SDK checks; callers should use 474 * {@link #setRequireCompatChange(long, boolean)} instead, 475 * possibly combined with 476 * {@link Intent#FLAG_RECEIVER_REGISTERED_ONLY}. 477 * @hide 478 */ 479 @Deprecated setMinManifestReceiverApiLevel(int apiLevel)480 public void setMinManifestReceiverApiLevel(int apiLevel) { 481 mMinManifestReceiverApiLevel = apiLevel; 482 } 483 484 /** 485 * Return {@link #setMinManifestReceiverApiLevel}. 486 * 487 * @deprecated to give developers the most flexibility during beta releases, 488 * we strongly encourage using {@link ChangeId} instead of 489 * target SDK checks; callers should use 490 * {@link #setRequireCompatChange(long, boolean)} instead, 491 * possibly combined with 492 * {@link Intent#FLAG_RECEIVER_REGISTERED_ONLY}. 493 * @hide 494 */ 495 @Deprecated getMinManifestReceiverApiLevel()496 public int getMinManifestReceiverApiLevel() { 497 return mMinManifestReceiverApiLevel; 498 } 499 500 /** 501 * Set the maximum target API level of receivers of the broadcast. If an application 502 * is targeting an API level greater than this, the broadcast will not be delivered to 503 * them. This only applies to receivers declared in the app's AndroidManifest.xml. 504 * 505 * @deprecated to give developers the most flexibility during beta releases, 506 * we strongly encourage using {@link ChangeId} instead of 507 * target SDK checks; callers should use 508 * {@link #setRequireCompatChange(long, boolean)} instead, 509 * possibly combined with 510 * {@link Intent#FLAG_RECEIVER_REGISTERED_ONLY}. 511 * @hide 512 */ 513 @TestApi 514 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 515 @Deprecated setMaxManifestReceiverApiLevel(int apiLevel)516 public void setMaxManifestReceiverApiLevel(int apiLevel) { 517 mMaxManifestReceiverApiLevel = apiLevel; 518 } 519 520 /** 521 * Return {@link #setMaxManifestReceiverApiLevel}. 522 * 523 * @deprecated to give developers the most flexibility during beta releases, 524 * we strongly encourage using {@link ChangeId} instead of 525 * target SDK checks; callers should use 526 * {@link #setRequireCompatChange(long, boolean)} instead, 527 * possibly combined with 528 * {@link Intent#FLAG_RECEIVER_REGISTERED_ONLY}. 529 * @hide 530 */ 531 @TestApi 532 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 533 @Deprecated getMaxManifestReceiverApiLevel()534 public int getMaxManifestReceiverApiLevel() { 535 return mMaxManifestReceiverApiLevel; 536 } 537 538 /** 539 * Sets whether pending intent can be sent for an application with background restrictions 540 * @param dontSendToRestrictedApps if true, pending intent will not be sent for an application 541 * with background restrictions. Default value is {@code false} 542 * @hide 543 */ 544 @SystemApi setDontSendToRestrictedApps(boolean dontSendToRestrictedApps)545 public void setDontSendToRestrictedApps(boolean dontSendToRestrictedApps) { 546 if (dontSendToRestrictedApps) { 547 mFlags |= FLAG_DONT_SEND_TO_RESTRICTED_APPS; 548 } else { 549 mFlags &= ~FLAG_DONT_SEND_TO_RESTRICTED_APPS; 550 } 551 } 552 553 /** 554 * @hide 555 * @return #setDontSendToRestrictedApps 556 */ isDontSendToRestrictedApps()557 public boolean isDontSendToRestrictedApps() { 558 return (mFlags & FLAG_DONT_SEND_TO_RESTRICTED_APPS) != 0; 559 } 560 561 /** 562 * Sets the process will be able to start activities from background for the duration of 563 * the broadcast dispatch. Default value is {@code false} 564 * @hide 565 */ 566 @SystemApi 567 @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) setBackgroundActivityStartsAllowed(boolean allowBackgroundActivityStarts)568 public void setBackgroundActivityStartsAllowed(boolean allowBackgroundActivityStarts) { 569 if (allowBackgroundActivityStarts) { 570 mFlags |= FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS; 571 } else { 572 mFlags &= ~FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS; 573 } 574 } 575 576 /** 577 * @hide 578 * @return #setAllowBackgroundActivityStarts 579 */ 580 @Deprecated allowsBackgroundActivityStarts()581 public boolean allowsBackgroundActivityStarts() { 582 return (mFlags & FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0; 583 } 584 585 /** 586 * Use this to configure a broadcast to be sent to apps that hold all permissions in 587 * the list. This is only for use with the {@link Context#sendBroadcast(Intent intent, 588 * @Nullable String receiverPermission, @Nullable Bundle options)}. 589 * 590 * <p> If both {@link #setRequireAllOfPermissions(String[])} and 591 * {@link #setRequireNoneOfPermissions(String[])} are used, then receivers must have all of the 592 * permissions set by {@link #setRequireAllOfPermissions(String[])}, and none of the 593 * permissions set by {@link #setRequireNoneOfPermissions(String[])} to get the broadcast. 594 * 595 * @param requiredPermissions a list of Strings of permission the receiver must have. Set to 596 * null or an empty array to clear any previously set value. 597 * @hide 598 */ 599 @SystemApi setRequireAllOfPermissions(@ullable String[] requiredPermissions)600 public void setRequireAllOfPermissions(@Nullable String[] requiredPermissions) { 601 mRequireAllOfPermissions = requiredPermissions; 602 } 603 604 /** 605 * Use this to configure a broadcast to be sent to apps that don't hold any permissions in 606 * list. This is only for use with the {@link Context#sendBroadcast(Intent intent, 607 * @Nullable String receiverPermission, @Nullable Bundle options)}. 608 * 609 * <p> If both {@link #setRequireAllOfPermissions(String[])} and 610 * {@link #setRequireNoneOfPermissions(String[])} are used, then receivers must have all of the 611 * permissions set by {@link #setRequireAllOfPermissions(String[])}, and none of the 612 * permissions set by {@link #setRequireNoneOfPermissions(String[])} to get the broadcast. 613 * 614 * @param excludedPermissions a list of Strings of permission the receiver must not have. Set to 615 * null or an empty array to clear any previously set value. 616 * @hide 617 */ 618 @SystemApi setRequireNoneOfPermissions(@ullable String[] excludedPermissions)619 public void setRequireNoneOfPermissions(@Nullable String[] excludedPermissions) { 620 mRequireNoneOfPermissions = excludedPermissions; 621 } 622 623 /** 624 * When set, this broadcast will only be delivered to apps which have the 625 * given {@link ChangeId} in the given state. 626 * <p> 627 * Each {@link BroadcastOptions} instance supports only a single 628 * {@link ChangeId} requirement, so any subsequent calls will override any 629 * previously defined requirement. 630 * <p> 631 * This requirement applies to both manifest registered and runtime 632 * registered receivers. 633 * @hide 634 * 635 * @param changeId the {@link ChangeId} to inspect 636 * @param enabled the required enabled state of the inspected 637 * {@link ChangeId} for this broadcast to be delivered 638 * @see CompatChanges#isChangeEnabled 639 * @see #clearRequireCompatChange() 640 */ 641 @SystemApi setRequireCompatChange(long changeId, boolean enabled)642 public void setRequireCompatChange(long changeId, boolean enabled) { 643 mRequireCompatChangeId = changeId; 644 if (enabled) { 645 mFlags |= FLAG_REQUIRE_COMPAT_CHANGE_ENABLED; 646 } else { 647 mFlags &= ~FLAG_REQUIRE_COMPAT_CHANGE_ENABLED; 648 } 649 } 650 651 /** 652 * Clear any previously defined requirement for this broadcast requested via 653 * {@link #setRequireCompatChange(long, boolean)}. 654 * @hide 655 */ 656 @SystemApi clearRequireCompatChange()657 public void clearRequireCompatChange() { 658 setRequireCompatChange(CHANGE_INVALID, true); 659 } 660 661 /** 662 * When set, this broadcast will be understood as having originated from an 663 * alarm going off. Only the OS itself can use this option; uses by other 664 * senders will be ignored. 665 * @hide 666 * 667 * @param senderIsAlarm Whether the broadcast is alarm-triggered. 668 */ setAlarmBroadcast(boolean senderIsAlarm)669 public void setAlarmBroadcast(boolean senderIsAlarm) { 670 if (senderIsAlarm) { 671 mFlags |= FLAG_IS_ALARM_BROADCAST; 672 } else { 673 mFlags &= ~FLAG_IS_ALARM_BROADCAST; 674 } 675 } 676 677 /** 678 * Did this broadcast originate from an alarm triggering? 679 * @return true if this broadcast is an alarm message, false otherwise 680 * @hide 681 */ isAlarmBroadcast()682 public boolean isAlarmBroadcast() { 683 return (mFlags & FLAG_IS_ALARM_BROADCAST) != 0; 684 } 685 686 /** 687 * Sets whether the identity of the broadcasting app should be shared with all receivers 688 * that will receive this broadcast. 689 * 690 * <p>Use this option when broadcasting to a receiver that needs to know the identity of the 691 * broadcaster; with this set to {@code true}, the receiver will have access to the broadcasting 692 * app's package name and uid. 693 * 694 * <p>Defaults to {@code false} if not set. 695 * 696 * @param shareIdentityEnabled whether the broadcasting app's identity should be shared with the 697 * receiver 698 * @return {@code this} {@link BroadcastOptions} instance 699 * @see BroadcastReceiver#getSentFromUid() 700 * @see BroadcastReceiver#getSentFromPackage() 701 */ setShareIdentityEnabled(boolean shareIdentityEnabled)702 public @NonNull BroadcastOptions setShareIdentityEnabled(boolean shareIdentityEnabled) { 703 if (shareIdentityEnabled) { 704 mFlags |= FLAG_SHARE_IDENTITY; 705 } else { 706 mFlags &= ~FLAG_SHARE_IDENTITY; 707 } 708 return this; 709 } 710 711 /** 712 * Returns whether the broadcasting app has opted-in to sharing its identity with the receiver. 713 * 714 * @return {@code true} if the broadcasting app has opted in to sharing its identity 715 * @see #setShareIdentityEnabled(boolean) 716 * @see BroadcastReceiver#getSentFromUid() 717 * @see BroadcastReceiver#getSentFromPackage() 718 */ isShareIdentityEnabled()719 public boolean isShareIdentityEnabled() { 720 return (mFlags & FLAG_SHARE_IDENTITY) != 0; 721 } 722 723 /** 724 * Did this broadcast originate from a push message from the server? 725 * 726 * @return true if this broadcast is a push message, false otherwise. 727 * @hide 728 */ isPushMessagingBroadcast()729 public boolean isPushMessagingBroadcast() { 730 return mTemporaryAppAllowlistReasonCode == PowerExemptionManager.REASON_PUSH_MESSAGING; 731 } 732 733 /** 734 * Did this broadcast originate from a push message from the server which was over the allowed 735 * quota? 736 * 737 * @return true if this broadcast is a push message over quota, false otherwise. 738 * @hide 739 */ isPushMessagingOverQuotaBroadcast()740 public boolean isPushMessagingOverQuotaBroadcast() { 741 return mTemporaryAppAllowlistReasonCode 742 == PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA; 743 } 744 745 /** {@hide} */ getRequireCompatChangeId()746 public long getRequireCompatChangeId() { 747 return mRequireCompatChangeId; 748 } 749 750 /** 751 * Test if the given app meets the {@link ChangeId} state required by this 752 * broadcast, if any. 753 * 754 * @hide 755 */ 756 @TestApi 757 @android.ravenwood.annotation.RavenwoodThrow testRequireCompatChange(int uid)758 public boolean testRequireCompatChange(int uid) { 759 if (mRequireCompatChangeId != CHANGE_INVALID) { 760 final boolean requireEnabled = (mFlags & FLAG_REQUIRE_COMPAT_CHANGE_ENABLED) != 0; 761 return CompatChanges.isChangeEnabled(mRequireCompatChangeId, uid) == requireEnabled; 762 } else { 763 return true; 764 } 765 } 766 767 /** 768 * Sets whether events (such as posting a notification) originating from an app after it 769 * receives the broadcast while in background should be recorded as responses to the broadcast. 770 * 771 * <p> Note that this will only be considered when sending explicit broadcast intents. 772 * 773 * @param id ID to be used for the response events corresponding to this broadcast. If the 774 * value is {@code 0} (default), then response events will not be recorded. Otherwise, 775 * they will be recorded with the ID provided. 776 * 777 * @hide 778 */ 779 @SystemApi 780 @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) recordResponseEventWhileInBackground(@ntRangefrom = 0) long id)781 public void recordResponseEventWhileInBackground(@IntRange(from = 0) long id) { 782 mIdForResponseEvent = id; 783 } 784 785 /** @hide */ 786 @IntRange(from = 0) getIdForResponseEvent()787 public long getIdForResponseEvent() { 788 return mIdForResponseEvent; 789 } 790 791 /** 792 * Sets deferral policy for this broadcast that specifies how this broadcast 793 * can be deferred for delivery at some future point. 794 */ setDeferralPolicy(@eferralPolicy int deferralPolicy)795 public @NonNull BroadcastOptions setDeferralPolicy(@DeferralPolicy int deferralPolicy) { 796 mDeferralPolicy = deferralPolicy; 797 return this; 798 } 799 800 /** 801 * Gets deferral policy for this broadcast that specifies how this broadcast 802 * can be deferred for delivery at some future point. 803 */ getDeferralPolicy()804 public @DeferralPolicy int getDeferralPolicy() { 805 return mDeferralPolicy; 806 } 807 808 /** 809 * Clears any deferral policy for this broadcast that specifies how this 810 * broadcast can be deferred for delivery at some future point. 811 */ clearDeferralPolicy()812 public void clearDeferralPolicy() { 813 mDeferralPolicy = DEFERRAL_POLICY_DEFAULT; 814 } 815 816 /** 817 * Set delivery group policy for this broadcast to specify how multiple broadcasts belonging to 818 * the same delivery group has to be handled. 819 */ 820 @NonNull setDeliveryGroupPolicy(@eliveryGroupPolicy int policy)821 public BroadcastOptions setDeliveryGroupPolicy(@DeliveryGroupPolicy int policy) { 822 mDeliveryGroupPolicy = policy; 823 return this; 824 } 825 826 /** 827 * Get the delivery group policy for this broadcast that specifies how multiple broadcasts 828 * belonging to the same delivery group has to be handled. 829 */ getDeliveryGroupPolicy()830 public @DeliveryGroupPolicy int getDeliveryGroupPolicy() { 831 return mDeliveryGroupPolicy; 832 } 833 834 /** 835 * Clears any previously set delivery group policies using 836 * {@link #setDeliveryGroupMatchingKey(String, String)} and resets the delivery group policy to 837 * the default value ({@link #DELIVERY_GROUP_POLICY_ALL}). 838 */ clearDeliveryGroupPolicy()839 public void clearDeliveryGroupPolicy() { 840 mDeliveryGroupPolicy = DELIVERY_GROUP_POLICY_ALL; 841 } 842 843 /** 844 * Set namespace and key to identify the delivery group that this broadcast belongs to. 845 * 846 * <p> If {@code namespace} and {@code key} are specified, then another broadcast will be 847 * considered to be in the same delivery group as this iff it has the same {@code namespace} 848 * and {@code key}. 849 * 850 * <p> If not matching key using this API then by default 851 * {@link Intent#filterEquals(Intent)} will be used to identify the delivery group. 852 */ 853 @NonNull setDeliveryGroupMatchingKey(@onNull String namespace, @NonNull String key)854 public BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String namespace, 855 @NonNull String key) { 856 mDeliveryGroupMatchingNamespaceFragment = Objects.requireNonNull(namespace); 857 mDeliveryGroupMatchingKeyFragment = Objects.requireNonNull(key); 858 return this; 859 } 860 861 /** 862 * Return the namespace and key that is used to identify the delivery group that this 863 * broadcast belongs to. 864 * 865 * @return the delivery group namespace and key that was previously set using 866 * {@link #setDeliveryGroupMatchingKey(String, String)}, concatenated with a {@code :}. 867 */ 868 @Nullable getDeliveryGroupMatchingKey()869 public String getDeliveryGroupMatchingKey() { 870 if (mDeliveryGroupMatchingNamespaceFragment == null 871 || mDeliveryGroupMatchingKeyFragment == null) { 872 return null; 873 } 874 return String.join(":", mDeliveryGroupMatchingNamespaceFragment, 875 mDeliveryGroupMatchingKeyFragment); 876 } 877 878 /** 879 * Return the namespace fragment that is used to identify the delivery group that this 880 * broadcast belongs to. 881 * 882 * @return the delivery group namespace fragment that was previously set using 883 * {@link #setDeliveryGroupMatchingKey(String, String)}. 884 * @hide 885 */ 886 @Nullable getDeliveryGroupMatchingNamespaceFragment()887 public String getDeliveryGroupMatchingNamespaceFragment() { 888 return mDeliveryGroupMatchingNamespaceFragment; 889 } 890 891 /** 892 * Return the key fragment that is used to identify the delivery group that this 893 * broadcast belongs to. 894 * 895 * @return the delivery group key fragment that was previously set using 896 * {@link #setDeliveryGroupMatchingKey(String, String)}. 897 * @hide 898 */ 899 @Nullable getDeliveryGroupMatchingKeyFragment()900 public String getDeliveryGroupMatchingKeyFragment() { 901 return mDeliveryGroupMatchingKeyFragment; 902 } 903 904 /** 905 * Clears the namespace and key that was previously set using 906 * {@link #setDeliveryGroupMatchingKey(String, String)}. 907 */ clearDeliveryGroupMatchingKey()908 public void clearDeliveryGroupMatchingKey() { 909 mDeliveryGroupMatchingNamespaceFragment = null; 910 mDeliveryGroupMatchingKeyFragment = null; 911 } 912 913 /** 914 * Set the {@link IntentFilter} object to identify the delivery group that this broadcast 915 * belongs to. 916 * 917 * <p> If a {@code matchingFilter} is specified, then another broadcast will be considered 918 * to be in the same delivery group as this iff the {@code matchingFilter} matches it's intent. 919 * 920 * <p> If neither matching key using {@link #setDeliveryGroupMatchingKey(String, String)} nor 921 * matching filter using this API is specified, then by default 922 * {@link Intent#filterEquals(Intent)} will be used to identify the delivery group. 923 * 924 * @hide 925 */ 926 @NonNull setDeliveryGroupMatchingFilter(@onNull IntentFilter matchingFilter)927 public BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull IntentFilter matchingFilter) { 928 mDeliveryGroupMatchingFilter = Objects.requireNonNull(matchingFilter); 929 return this; 930 } 931 932 /** 933 * Return the {@link IntentFilter} object that is used to identify the delivery group 934 * that this broadcast belongs to. 935 * 936 * @return the {@link IntentFilter} object that was previously set using 937 * {@link #setDeliveryGroupMatchingFilter(IntentFilter)}. 938 * @hide 939 */ 940 @Nullable getDeliveryGroupMatchingFilter()941 public IntentFilter getDeliveryGroupMatchingFilter() { 942 return mDeliveryGroupMatchingFilter; 943 } 944 945 /** 946 * Clears the {@link IntentFilter} object that was previously set using 947 * {@link #setDeliveryGroupMatchingFilter(IntentFilter)}. 948 * 949 * @hide 950 */ clearDeliveryGroupMatchingFilter()951 public void clearDeliveryGroupMatchingFilter() { 952 mDeliveryGroupMatchingFilter = null; 953 } 954 955 /** 956 * Set the {@link BundleMerger} that specifies how to merge the extras data from 957 * broadcasts in a delivery group. 958 * 959 * <p>Note that this value will be ignored if the delivery group policy is not set as 960 * {@link #DELIVERY_GROUP_POLICY_MERGED}. 961 * 962 * @hide 963 */ 964 @NonNull setDeliveryGroupExtrasMerger(@onNull BundleMerger extrasMerger)965 public BroadcastOptions setDeliveryGroupExtrasMerger(@NonNull BundleMerger extrasMerger) { 966 mDeliveryGroupExtrasMerger = Objects.requireNonNull(extrasMerger); 967 return this; 968 } 969 970 /** 971 * Return the {@link BundleMerger} that specifies how to merge the extras data from 972 * broadcasts in a delivery group. 973 * 974 * @return the {@link BundleMerger} object that was previously set using 975 * {@link #setDeliveryGroupExtrasMerger(BundleMerger)}. 976 * @hide 977 */ 978 @Nullable getDeliveryGroupExtrasMerger()979 public BundleMerger getDeliveryGroupExtrasMerger() { 980 return mDeliveryGroupExtrasMerger; 981 } 982 983 /** 984 * Clear the {@link BundleMerger} object that was previously set using 985 * {@link #setDeliveryGroupExtrasMerger(BundleMerger)}. 986 * @hide 987 */ clearDeliveryGroupExtrasMerger()988 public void clearDeliveryGroupExtrasMerger() { 989 mDeliveryGroupExtrasMerger = null; 990 } 991 992 /** 993 * Sets whether the broadcast should be considered as having originated from 994 * some direct interaction by the user such as a notification tap or button 995 * press. This signal is used internally to ensure the broadcast is 996 * delivered quickly with low latency. 997 * 998 * @hide 999 */ 1000 @RequiresPermission(android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE) setInteractive(boolean interactive)1001 public @NonNull BroadcastOptions setInteractive(boolean interactive) { 1002 if (interactive) { 1003 mFlags |= FLAG_INTERACTIVE; 1004 } else { 1005 mFlags &= ~FLAG_INTERACTIVE; 1006 } 1007 return this; 1008 } 1009 1010 /** 1011 * Returns whether the broadcast should be considered as having originated 1012 * from some direct interaction by the user such as a notification tap or 1013 * button press. 1014 * 1015 * @hide 1016 */ 1017 @RequiresPermission(android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE) isInteractive()1018 public boolean isInteractive() { 1019 return (mFlags & FLAG_INTERACTIVE) != 0; 1020 } 1021 1022 /** 1023 * Set PendingIntent activity is allowed to be started in the background if the caller 1024 * can start background activities. 1025 * 1026 * @deprecated use #setPendingIntentBackgroundActivityStartMode(int) to set the full range 1027 * of states 1028 * @hide 1029 */ 1030 @SystemApi 1031 @Override setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed)1032 @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) { 1033 super.setPendingIntentBackgroundActivityLaunchAllowed(allowed); 1034 } 1035 1036 /** 1037 * Get PendingIntent activity is allowed to be started in the background if the caller can start 1038 * background activities. 1039 * 1040 * @deprecated use {@link #getPendingIntentBackgroundActivityStartMode()} since for apps 1041 * targeting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or higher this value might 1042 * not match the actual behavior if the value was not explicitly set. 1043 * @hide 1044 */ 1045 @SystemApi 1046 @Override isPendingIntentBackgroundActivityLaunchAllowed()1047 @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed() { 1048 return super.isPendingIntentBackgroundActivityLaunchAllowed(); 1049 } 1050 1051 1052 /** 1053 * Sets the mode for allowing or denying the senders privileges to start background activities 1054 * to the PendingIntent. 1055 * 1056 * This is typically used when executing {@link PendingIntent#send(Bundle)} or similar 1057 * methods. A privileged sender of a PendingIntent should only grant 1058 * MODE_BACKGROUND_ACTIVITY_START_ALLOWED if the PendingIntent is from a trusted source and/or 1059 * executed on behalf the user. 1060 * @hide 1061 */ 1062 @SystemApi 1063 @NonNull 1064 @Override // to narrow down the return type setPendingIntentBackgroundActivityStartMode( @ackgroundActivityStartMode int state)1065 public BroadcastOptions setPendingIntentBackgroundActivityStartMode( 1066 @BackgroundActivityStartMode int state) { 1067 super.setPendingIntentBackgroundActivityStartMode(state); 1068 return this; 1069 } 1070 1071 /** 1072 * Gets the mode for allowing or denying the senders privileges to start background activities 1073 * to the PendingIntent. 1074 * 1075 * @see #setPendingIntentBackgroundActivityStartMode(int) 1076 * @hide 1077 */ 1078 @SystemApi 1079 @Override // to narrow down the return type getPendingIntentBackgroundActivityStartMode()1080 public @BackgroundActivityStartMode int getPendingIntentBackgroundActivityStartMode() { 1081 return super.getPendingIntentBackgroundActivityStartMode(); 1082 } 1083 1084 /** 1085 * Returns the created options as a Bundle, which can be passed to 1086 * {@link android.content.Context#sendBroadcast(android.content.Intent) 1087 * Context.sendBroadcast(Intent)} and related methods. 1088 * Note that the returned Bundle is still owned by the BroadcastOptions 1089 * object; you must not modify it, but can supply it to the sendBroadcast 1090 * methods that take an options Bundle. 1091 * 1092 * @throws IllegalStateException if the broadcast option values are inconsistent. For example, 1093 * if the delivery group policy is specified as "MERGED" but no 1094 * extras merger is supplied. 1095 */ 1096 @Override toBundle()1097 public @NonNull Bundle toBundle() { 1098 Bundle b = super.toBundle(); 1099 if (mFlags != 0) { 1100 b.putInt(KEY_FLAGS, mFlags); 1101 } 1102 if (isTemporaryAppAllowlistSet()) { 1103 b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration); 1104 b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType); 1105 b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, mTemporaryAppAllowlistReasonCode); 1106 b.putString(KEY_TEMPORARY_APP_ALLOWLIST_REASON, mTemporaryAppAllowlistReason); 1107 } 1108 if (mMinManifestReceiverApiLevel != 0) { 1109 b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel); 1110 } 1111 if (mMaxManifestReceiverApiLevel != Build.VERSION_CODES.CUR_DEVELOPMENT) { 1112 b.putInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, mMaxManifestReceiverApiLevel); 1113 } 1114 if (mRequireAllOfPermissions != null) { 1115 b.putStringArray(KEY_REQUIRE_ALL_OF_PERMISSIONS, mRequireAllOfPermissions); 1116 } 1117 if (mRequireNoneOfPermissions != null) { 1118 b.putStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS, mRequireNoneOfPermissions); 1119 } 1120 if (mRequireCompatChangeId != CHANGE_INVALID) { 1121 b.putLong(KEY_REQUIRE_COMPAT_CHANGE_ID, mRequireCompatChangeId); 1122 } 1123 if (mIdForResponseEvent != 0) { 1124 b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent); 1125 } 1126 if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) { 1127 b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy); 1128 } 1129 if (mDeliveryGroupMatchingNamespaceFragment != null) { 1130 b.putString(KEY_DELIVERY_GROUP_NAMESPACE, mDeliveryGroupMatchingNamespaceFragment); 1131 } 1132 if (mDeliveryGroupMatchingKeyFragment != null) { 1133 b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKeyFragment); 1134 } 1135 if (mDeliveryGroupPolicy == DELIVERY_GROUP_POLICY_MERGED) { 1136 if (mDeliveryGroupExtrasMerger != null) { 1137 b.putParcelable(KEY_DELIVERY_GROUP_EXTRAS_MERGER, 1138 mDeliveryGroupExtrasMerger); 1139 } else { 1140 throw new IllegalStateException("Extras merger cannot be empty " 1141 + "when delivery group policy is 'MERGED'"); 1142 } 1143 } 1144 if (mDeliveryGroupMatchingFilter != null) { 1145 b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter); 1146 } 1147 if (mDeferralPolicy != DEFERRAL_POLICY_DEFAULT) { 1148 b.putInt(KEY_DEFERRAL_POLICY, mDeferralPolicy); 1149 } 1150 return b; 1151 } 1152 1153 /** 1154 * Returns a {@link BroadcastOptions} parsed from the given {@link Bundle}, 1155 * typically generated from {@link #toBundle()}. 1156 */ fromBundle(@onNull Bundle options)1157 public static @NonNull BroadcastOptions fromBundle(@NonNull Bundle options) { 1158 return new BroadcastOptions(options); 1159 } 1160 1161 /** {@hide} */ fromBundleNullable(@ullable Bundle options)1162 public static @Nullable BroadcastOptions fromBundleNullable(@Nullable Bundle options) { 1163 return (options != null) ? new BroadcastOptions(options) : null; 1164 } 1165 } 1166