1 /* 2 * Copyright (C) 2021 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.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SuppressLint; 23 import android.annotation.TestApi; 24 import android.os.Bundle; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 29 /** 30 * Base class for {@link ActivityOptions} and {@link BroadcastOptions}. 31 * @hide 32 */ 33 // Expose the methods and constants required to test the SystemApis in subclasses. 34 @TestApi 35 // Suppressed since lint is recommending class have a suffix of Params. 36 @SuppressLint("UserHandleName") 37 public class ComponentOptions { 38 39 /** 40 * PendingIntent caller allows activity start even if PendingIntent creator is in background. 41 * This only works if the PendingIntent caller is allowed to start background activities, 42 * for example if it's in the foreground, or has BAL permission. 43 * @hide 44 */ 45 public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED = 46 "android.pendingIntent.backgroundActivityAllowed"; 47 48 /** 49 * PendingIntent caller allows activity to be started if caller has BAL permission. 50 * @hide 51 */ 52 public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION = 53 "android.pendingIntent.backgroundActivityAllowedByPermission"; 54 55 private @Nullable Boolean mPendingIntentBalAllowed = null; 56 private boolean mPendingIntentBalAllowedByPermission = false; 57 58 /** @hide */ 59 @Retention(RetentionPolicy.SOURCE) 60 @IntDef(prefix = {"MODE_BACKGROUND_ACTIVITY_START_"}, value = { 61 MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED, 62 MODE_BACKGROUND_ACTIVITY_START_ALLOWED, 63 MODE_BACKGROUND_ACTIVITY_START_DENIED}) 64 public @interface BackgroundActivityStartMode {} 65 /** 66 * No explicit value chosen. The system will decide whether to grant privileges. 67 * @hide 68 */ 69 @TestApi 70 public static final int MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED = 0; 71 /** 72 * Allow the {@link PendingIntent} to use the background activity start privileges. 73 * @hide 74 */ 75 @TestApi 76 public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOWED = 1; 77 /** 78 * Deny the {@link PendingIntent} to use the background activity start privileges. 79 * @hide 80 */ 81 @TestApi 82 public static final int MODE_BACKGROUND_ACTIVITY_START_DENIED = 2; 83 ComponentOptions()84 ComponentOptions() { 85 } 86 ComponentOptions(Bundle opts)87 ComponentOptions(Bundle opts) { 88 // If the remote side sent us bad parcelables, they won't get the 89 // results they want, which is their loss. 90 opts.setDefusable(true); 91 92 boolean pendingIntentBalAllowedIsSetExplicitly = 93 opts.containsKey(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED); 94 if (pendingIntentBalAllowedIsSetExplicitly) { 95 mPendingIntentBalAllowed = 96 opts.getBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED); 97 } 98 setPendingIntentBackgroundActivityLaunchAllowedByPermission( 99 opts.getBoolean( 100 KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, false)); 101 } 102 103 /** 104 * Set PendingIntent activity is allowed to be started in the background if the caller 105 * can start background activities. 106 * 107 * @deprecated use #setPendingIntentBackgroundActivityStartMode(int) to set the full range 108 * of states 109 * @hide 110 */ setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed)111 @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) { 112 mPendingIntentBalAllowed = allowed; 113 } 114 115 /** 116 * Get PendingIntent activity is allowed to be started in the background if the caller can start 117 * background activities. 118 * 119 * @deprecated use {@link #getPendingIntentBackgroundActivityStartMode()} since for apps 120 * targeting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or higher this value might 121 * not match the actual behavior if the value was not explicitly set. 122 * @hide 123 */ isPendingIntentBackgroundActivityLaunchAllowed()124 @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed() { 125 if (mPendingIntentBalAllowed == null) { 126 // cannot return null, so return the value used up to API level 33 for compatibility 127 return true; 128 } 129 return mPendingIntentBalAllowed; 130 } 131 132 /** 133 * Sets the mode for allowing or denying the senders privileges to start background activities 134 * to the PendingIntent. 135 * 136 * This is typically used in when executing {@link PendingIntent#send(Bundle)} or similar 137 * methods. A privileged sender of a PendingIntent should only grant 138 * {@link #MODE_BACKGROUND_ACTIVITY_START_ALLOWED} if the PendingIntent is from a trusted source 139 * and/or executed on behalf the user. 140 * @hide 141 */ setPendingIntentBackgroundActivityStartMode( @ackgroundActivityStartMode int state)142 public @NonNull ComponentOptions setPendingIntentBackgroundActivityStartMode( 143 @BackgroundActivityStartMode int state) { 144 switch (state) { 145 case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED: 146 mPendingIntentBalAllowed = null; 147 break; 148 case MODE_BACKGROUND_ACTIVITY_START_ALLOWED: 149 mPendingIntentBalAllowed = true; 150 break; 151 case MODE_BACKGROUND_ACTIVITY_START_DENIED: 152 mPendingIntentBalAllowed = false; 153 break; 154 default: 155 throw new IllegalArgumentException(state + " is not valid"); 156 } 157 return this; 158 } 159 160 /** 161 * Gets the mode for allowing or denying the senders privileges to start background activities 162 * to the PendingIntent. 163 * @hide 164 * 165 * @see #setPendingIntentBackgroundActivityStartMode(int) 166 */ getPendingIntentBackgroundActivityStartMode()167 public @BackgroundActivityStartMode int getPendingIntentBackgroundActivityStartMode() { 168 if (mPendingIntentBalAllowed == null) { 169 return MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; 170 } else if (mPendingIntentBalAllowed) { 171 return MODE_BACKGROUND_ACTIVITY_START_ALLOWED; 172 } else { 173 return MODE_BACKGROUND_ACTIVITY_START_DENIED; 174 } 175 } 176 177 /** 178 * Set PendingIntent activity can be launched from background if caller has BAL permission. 179 * @hide 180 */ setPendingIntentBackgroundActivityLaunchAllowedByPermission(boolean allowed)181 public void setPendingIntentBackgroundActivityLaunchAllowedByPermission(boolean allowed) { 182 mPendingIntentBalAllowedByPermission = allowed; 183 } 184 185 /** 186 * Get PendingIntent activity is allowed to be started in the background if the caller 187 * has BAL permission. 188 * @hide 189 */ isPendingIntentBackgroundActivityLaunchAllowedByPermission()190 public boolean isPendingIntentBackgroundActivityLaunchAllowedByPermission() { 191 return mPendingIntentBalAllowedByPermission; 192 } 193 194 /** @hide */ toBundle()195 public Bundle toBundle() { 196 Bundle b = new Bundle(); 197 if (mPendingIntentBalAllowed != null) { 198 b.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, mPendingIntentBalAllowed); 199 } 200 if (mPendingIntentBalAllowedByPermission) { 201 b.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, 202 mPendingIntentBalAllowedByPermission); 203 } 204 return b; 205 } 206 207 /** @hide */ fromBundle(@ullable Bundle options)208 public static @Nullable ComponentOptions fromBundle(@Nullable Bundle options) { 209 return (options != null) ? new ComponentOptions(options) : null; 210 } 211 } 212