• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.os.Build;
25 import android.os.Bundle;
26 import android.os.PowerExemptionManager;
27 import android.os.PowerExemptionManager.ReasonCode;
28 import android.os.PowerExemptionManager.TempAllowListType;
29 
30 /**
31  * Helper class for building an options Bundle that can be used with
32  * {@link android.content.Context#sendBroadcast(android.content.Intent)
33  * Context.sendBroadcast(Intent)} and related methods.
34  * {@hide}
35  */
36 @SystemApi
37 public class BroadcastOptions {
38     private long mTemporaryAppAllowlistDuration;
39     private @TempAllowListType int mTemporaryAppAllowlistType;
40     private @ReasonCode int mTemporaryAppAllowlistReasonCode;
41     private @Nullable String mTemporaryAppAllowlistReason;
42     private int mMinManifestReceiverApiLevel = 0;
43     private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
44     private boolean mDontSendToRestrictedApps = false;
45     private boolean mAllowBackgroundActivityStarts;
46 
47     /**
48      * How long to temporarily put an app on the power allowlist when executing this broadcast
49      * to it.
50      */
51     private static final String KEY_TEMPORARY_APP_ALLOWLIST_DURATION
52             = "android:broadcast.temporaryAppAllowlistDuration";
53 
54     private static final String KEY_TEMPORARY_APP_ALLOWLIST_TYPE
55             = "android:broadcast.temporaryAppAllowlistType";
56 
57     private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE =
58             "android:broadcast.temporaryAppAllowlistReasonCode";
59 
60     private static final String KEY_TEMPORARY_APP_ALLOWLIST_REASON =
61             "android:broadcast.temporaryAppAllowlistReason";
62 
63     /**
64      * Corresponds to {@link #setMinManifestReceiverApiLevel}.
65      */
66     private static final String KEY_MIN_MANIFEST_RECEIVER_API_LEVEL
67             = "android:broadcast.minManifestReceiverApiLevel";
68 
69     /**
70      * Corresponds to {@link #setMaxManifestReceiverApiLevel}.
71      */
72     private static final String KEY_MAX_MANIFEST_RECEIVER_API_LEVEL
73             = "android:broadcast.maxManifestReceiverApiLevel";
74 
75     /**
76      * Corresponds to {@link #setDontSendToRestrictedApps}.
77      */
78     private static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
79             "android:broadcast.dontSendToRestrictedApps";
80 
81     /**
82      * Corresponds to {@link #setBackgroundActivityStartsAllowed}.
83      */
84     private static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
85             "android:broadcast.allowBackgroundActivityStarts";
86 
87     /**
88      * @hide
89      * @deprecated Use {@link android.os.PowerExemptionManager#
90      * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED} instead.
91      */
92     @Deprecated
93     public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED =
94             PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
95 
96     /**
97      * @hide
98      * @deprecated Use {@link android.os.PowerExemptionManager#
99      * TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} instead.
100      */
101     @Deprecated
102     public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED =
103             PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
104 
makeBasic()105     public static BroadcastOptions makeBasic() {
106         BroadcastOptions opts = new BroadcastOptions();
107         return opts;
108     }
109 
BroadcastOptions()110     private BroadcastOptions() {
111         resetTemporaryAppAllowlist();
112     }
113 
114     /** @hide */
115     @TestApi
BroadcastOptions(@onNull Bundle opts)116     public BroadcastOptions(@NonNull Bundle opts) {
117         // Match the logic in toBundle().
118         if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) {
119             mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
120             mTemporaryAppAllowlistType = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE);
121             mTemporaryAppAllowlistReasonCode = opts.getInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE,
122                     PowerExemptionManager.REASON_UNKNOWN);
123             mTemporaryAppAllowlistReason = opts.getString(KEY_TEMPORARY_APP_ALLOWLIST_REASON);
124         } else {
125             resetTemporaryAppAllowlist();
126         }
127         mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
128         mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
129                 Build.VERSION_CODES.CUR_DEVELOPMENT);
130         mDontSendToRestrictedApps = opts.getBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, false);
131         mAllowBackgroundActivityStarts = opts.getBoolean(KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS,
132                 false);
133     }
134 
135     /**
136      * Set a duration for which the system should temporary place an application on the
137      * power allowlist when this broadcast is being delivered to it.
138      * @param duration The duration in milliseconds; 0 means to not place on allowlist.
139      * @deprecated use {@link #setTemporaryAppAllowlist(long, int, int,  String)} instead.
140      */
141     @Deprecated
142     @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
143             android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
144             android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
setTemporaryAppWhitelistDuration(long duration)145     public void setTemporaryAppWhitelistDuration(long duration) {
146         setTemporaryAppAllowlist(duration,
147                 PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
148                 PowerExemptionManager.REASON_UNKNOWN, null);
149     }
150 
151     /**
152      * Set a duration for which the system should temporary place an application on the
153      * power allowlist when this broadcast is being delivered to it, specify the temp allowlist
154      * type.
155      * @param duration the duration in milliseconds.
156      *                 0 means to not place on allowlist, and clears previous call to this method.
157      * @param type one of {@link TempAllowListType}.
158      *             {@link PowerExemptionManager#TEMPORARY_ALLOW_LIST_TYPE_NONE} means
159      *             to not place on allowlist, and clears previous call to this method.
160      * @param reasonCode one of {@link ReasonCode}, use
161      *                  {@link PowerExemptionManager#REASON_UNKNOWN} if not sure.
162      * @param reason A human-readable reason explaining why the app is temp allowlisted. Only
163      *               used for logging purposes. Could be null or empty string.
164      */
165     @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
166             android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
167             android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
setTemporaryAppAllowlist(long duration, @TempAllowListType int type, @ReasonCode int reasonCode, @Nullable String reason)168     public void setTemporaryAppAllowlist(long duration, @TempAllowListType int type,
169             @ReasonCode int reasonCode, @Nullable String reason) {
170         mTemporaryAppAllowlistDuration = duration;
171         mTemporaryAppAllowlistType = type;
172         mTemporaryAppAllowlistReasonCode = reasonCode;
173         mTemporaryAppAllowlistReason = reason;
174 
175         if (!isTemporaryAppAllowlistSet()) {
176             resetTemporaryAppAllowlist();
177         }
178     }
179 
isTemporaryAppAllowlistSet()180     private boolean isTemporaryAppAllowlistSet() {
181         return mTemporaryAppAllowlistDuration > 0
182                 && mTemporaryAppAllowlistType
183                     != PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
184     }
185 
resetTemporaryAppAllowlist()186     private void resetTemporaryAppAllowlist() {
187         mTemporaryAppAllowlistDuration = 0;
188         mTemporaryAppAllowlistType = PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
189         mTemporaryAppAllowlistReasonCode = PowerExemptionManager.REASON_UNKNOWN;
190         mTemporaryAppAllowlistReason = null;
191     }
192 
193     /**
194      * Return {@link #setTemporaryAppAllowlist}.
195      * @hide
196      */
197     @TestApi
getTemporaryAppAllowlistDuration()198     public long getTemporaryAppAllowlistDuration() {
199         return mTemporaryAppAllowlistDuration;
200     }
201 
202     /**
203      * Return {@link #mTemporaryAppAllowlistType}.
204      * @hide
205      */
206     @TestApi
getTemporaryAppAllowlistType()207     public @TempAllowListType int getTemporaryAppAllowlistType() {
208         return mTemporaryAppAllowlistType;
209     }
210 
211     /**
212      * Return {@link #mTemporaryAppAllowlistReasonCode}.
213      * @hide
214      */
215     @TestApi
getTemporaryAppAllowlistReasonCode()216     public @ReasonCode int getTemporaryAppAllowlistReasonCode() {
217         return mTemporaryAppAllowlistReasonCode;
218     }
219 
220     /**
221      * Return {@link #mTemporaryAppAllowlistReason}.
222      * @hide
223      */
224     @TestApi
getTemporaryAppAllowlistReason()225     public @Nullable String getTemporaryAppAllowlistReason() {
226         return mTemporaryAppAllowlistReason;
227     }
228 
229     /**
230      * Set the minimum target API level of receivers of the broadcast.  If an application
231      * is targeting an API level less than this, the broadcast will not be delivered to
232      * them.  This only applies to receivers declared in the app's AndroidManifest.xml.
233      * @hide
234      */
setMinManifestReceiverApiLevel(int apiLevel)235     public void setMinManifestReceiverApiLevel(int apiLevel) {
236         mMinManifestReceiverApiLevel = apiLevel;
237     }
238 
239     /**
240      * Return {@link #setMinManifestReceiverApiLevel}.
241      * @hide
242      */
getMinManifestReceiverApiLevel()243     public int getMinManifestReceiverApiLevel() {
244         return mMinManifestReceiverApiLevel;
245     }
246 
247     /**
248      * Set the maximum target API level of receivers of the broadcast.  If an application
249      * is targeting an API level greater than this, the broadcast will not be delivered to
250      * them.  This only applies to receivers declared in the app's AndroidManifest.xml.
251      * @hide
252      */
253     @TestApi
254     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
setMaxManifestReceiverApiLevel(int apiLevel)255     public void setMaxManifestReceiverApiLevel(int apiLevel) {
256         mMaxManifestReceiverApiLevel = apiLevel;
257     }
258 
259     /**
260      * Return {@link #setMaxManifestReceiverApiLevel}.
261      * @hide
262      */
263     @TestApi
264     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
getMaxManifestReceiverApiLevel()265     public int getMaxManifestReceiverApiLevel() {
266         return mMaxManifestReceiverApiLevel;
267     }
268 
269     /**
270      * Sets whether pending intent can be sent for an application with background restrictions
271      * @param dontSendToRestrictedApps if true, pending intent will not be sent for an application
272      * with background restrictions. Default value is {@code false}
273      */
setDontSendToRestrictedApps(boolean dontSendToRestrictedApps)274     public void setDontSendToRestrictedApps(boolean dontSendToRestrictedApps) {
275         mDontSendToRestrictedApps = dontSendToRestrictedApps;
276     }
277 
278     /**
279      * @hide
280      * @return #setDontSendToRestrictedApps
281      */
isDontSendToRestrictedApps()282     public boolean isDontSendToRestrictedApps() {
283         return mDontSendToRestrictedApps;
284     }
285 
286     /**
287      * Sets the process will be able to start activities from background for the duration of
288      * the broadcast dispatch. Default value is {@code false}
289      */
290     @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND)
setBackgroundActivityStartsAllowed(boolean allowBackgroundActivityStarts)291     public void setBackgroundActivityStartsAllowed(boolean allowBackgroundActivityStarts) {
292         mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
293     }
294 
295     /**
296      * @hide
297      * @return #setAllowBackgroundActivityStarts
298      */
allowsBackgroundActivityStarts()299     public boolean allowsBackgroundActivityStarts() {
300         return mAllowBackgroundActivityStarts;
301     }
302 
303     /**
304      * Returns the created options as a Bundle, which can be passed to
305      * {@link android.content.Context#sendBroadcast(android.content.Intent)
306      * Context.sendBroadcast(Intent)} and related methods.
307      * Note that the returned Bundle is still owned by the BroadcastOptions
308      * object; you must not modify it, but can supply it to the sendBroadcast
309      * methods that take an options Bundle.
310      */
toBundle()311     public Bundle toBundle() {
312         Bundle b = new Bundle();
313         if (isTemporaryAppAllowlistSet()) {
314             b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration);
315             b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType);
316             b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, mTemporaryAppAllowlistReasonCode);
317             b.putString(KEY_TEMPORARY_APP_ALLOWLIST_REASON, mTemporaryAppAllowlistReason);
318         }
319         if (mMinManifestReceiverApiLevel != 0) {
320             b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel);
321         }
322         if (mMaxManifestReceiverApiLevel != Build.VERSION_CODES.CUR_DEVELOPMENT) {
323             b.putInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, mMaxManifestReceiverApiLevel);
324         }
325         if (mDontSendToRestrictedApps) {
326             b.putBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, true);
327         }
328         if (mAllowBackgroundActivityStarts) {
329             b.putBoolean(KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS, true);
330         }
331         return b.isEmpty() ? null : b;
332     }
333 }
334