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 static android.app.ActivityOptions.BackgroundActivityStartMode; 20 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; 21 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS; 22 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT; 23 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; 24 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; 25 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE; 26 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.SuppressLint; 30 import android.annotation.TestApi; 31 import android.os.Bundle; 32 33 /** 34 * Base class for {@link ActivityOptions} and {@link BroadcastOptions}. 35 * @hide 36 */ 37 // Expose the methods and constants required to test the SystemApis in subclasses. 38 @TestApi 39 // Suppressed since lint is recommending class have a suffix of Params. 40 @SuppressLint("UserHandleName") 41 @android.ravenwood.annotation.RavenwoodKeepWholeClass 42 public class ComponentOptions { 43 44 /** 45 * PendingIntent caller allows activity start even if PendingIntent creator is in background. 46 * This only works if the PendingIntent caller is allowed to start background activities, 47 * for example if it's in the foreground, or has BAL permission. 48 * @hide 49 */ 50 public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED = 51 "android.pendingIntent.backgroundActivityAllowed"; 52 53 private Integer mPendingIntentBalAllowed = MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; 54 ComponentOptions()55 ComponentOptions() { 56 } 57 ComponentOptions(Bundle opts)58 ComponentOptions(Bundle opts) { 59 // If the remote side sent us bad parcelables, they won't get the 60 // results they want, which is their loss. 61 opts.setDefusable(true); 62 63 mPendingIntentBalAllowed = 64 opts.getInt(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, 65 MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED); 66 } 67 68 /** 69 * Set PendingIntent activity is allowed to be started in the background if the caller 70 * can start background activities. 71 * 72 * @deprecated use #setPendingIntentBackgroundActivityStartMode(int) to set the full range 73 * of states 74 * @hide 75 */ setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed)76 @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) { 77 mPendingIntentBalAllowed = allowed ? MODE_BACKGROUND_ACTIVITY_START_ALLOWED 78 : MODE_BACKGROUND_ACTIVITY_START_DENIED; 79 } 80 81 /** 82 * Get PendingIntent activity is allowed to be started in the background if the caller can start 83 * background activities. 84 * 85 * @deprecated use {@link #getPendingIntentBackgroundActivityStartMode()} since for apps 86 * targeting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or higher this value might 87 * not match the actual behavior if the value was not explicitly set. 88 * @hide 89 */ isPendingIntentBackgroundActivityLaunchAllowed()90 @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed() { 91 // cannot return all detail, so return the value used up to API level 33 for compatibility 92 return mPendingIntentBalAllowed != MODE_BACKGROUND_ACTIVITY_START_DENIED; 93 } 94 95 /** 96 * Sets the mode for allowing or denying the senders privileges to start background activities 97 * to the PendingIntent. 98 * 99 * This is typically used in when executing {@link PendingIntent#send(Bundle)} or similar 100 * methods. A privileged sender of a PendingIntent should only grant 101 * {@link #MODE_BACKGROUND_ACTIVITY_START_ALLOWED} if the PendingIntent is from a trusted source 102 * and/or executed on behalf the user. 103 * @hide 104 */ setPendingIntentBackgroundActivityStartMode( @ackgroundActivityStartMode int state)105 public @NonNull ComponentOptions setPendingIntentBackgroundActivityStartMode( 106 @BackgroundActivityStartMode int state) { 107 switch (state) { 108 case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED: 109 case MODE_BACKGROUND_ACTIVITY_START_DENIED: 110 case MODE_BACKGROUND_ACTIVITY_START_COMPAT: 111 case MODE_BACKGROUND_ACTIVITY_START_ALLOWED: 112 case MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS: 113 case MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE: 114 mPendingIntentBalAllowed = state; 115 break; 116 default: 117 // Assume that future values are some variant of allowing the start. 118 mPendingIntentBalAllowed = MODE_BACKGROUND_ACTIVITY_START_ALLOWED; 119 break; 120 } 121 return this; 122 } 123 124 /** 125 * Gets the mode for allowing or denying the senders privileges to start background activities 126 * to the PendingIntent. 127 * @hide 128 * 129 * @see #setPendingIntentBackgroundActivityStartMode(int) 130 */ getPendingIntentBackgroundActivityStartMode()131 public @BackgroundActivityStartMode int getPendingIntentBackgroundActivityStartMode() { 132 return mPendingIntentBalAllowed; 133 } 134 135 /** @hide */ toBundle()136 public Bundle toBundle() { 137 Bundle b = new Bundle(); 138 if (mPendingIntentBalAllowed != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED) { 139 b.putInt(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, mPendingIntentBalAllowed); 140 } 141 return b; 142 } 143 144 /** @hide */ fromBundle(@ullable Bundle options)145 public static @Nullable ComponentOptions fromBundle(@Nullable Bundle options) { 146 return (options != null) ? new ComponentOptions(options) : null; 147 } 148 } 149