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