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