• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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