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