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