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