diff options
6 files changed, 60 insertions, 38 deletions
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 9ea55f5ff84c..c6a1546fb931 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -103,7 +103,8 @@ public class ActivityOptions extends ComponentOptions { @IntDef(prefix = {"MODE_BACKGROUND_ACTIVITY_START_"}, value = { MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED, MODE_BACKGROUND_ACTIVITY_START_ALLOWED, - MODE_BACKGROUND_ACTIVITY_START_DENIED}) + MODE_BACKGROUND_ACTIVITY_START_DENIED, + MODE_BACKGROUND_ACTIVITY_START_COMPAT}) public @interface BackgroundActivityStartMode {} /** * No explicit value chosen. The system will decide whether to grant privileges. @@ -117,6 +118,13 @@ public class ActivityOptions extends ComponentOptions { * Deny the {@link PendingIntent} to use the background activity start privileges. */ public static final int MODE_BACKGROUND_ACTIVITY_START_DENIED = 2; + /** + * Special behavior for compatibility. + * Similar to {@link #MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED} + * + * @hide + */ + public static final int MODE_BACKGROUND_ACTIVITY_START_COMPAT = -1; /** * The package name that created the options. diff --git a/core/java/android/app/ComponentOptions.java b/core/java/android/app/ComponentOptions.java index 397477d72a9a..0e8e2e30c26f 100644 --- a/core/java/android/app/ComponentOptions.java +++ b/core/java/android/app/ComponentOptions.java @@ -18,6 +18,7 @@ package android.app; import static android.app.ActivityOptions.BackgroundActivityStartMode; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; @@ -54,7 +55,7 @@ public class ComponentOptions { public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION = "android.pendingIntent.backgroundActivityAllowedByPermission"; - private @Nullable Boolean mPendingIntentBalAllowed = null; + private Integer mPendingIntentBalAllowed = MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; private boolean mPendingIntentBalAllowedByPermission = false; ComponentOptions() { @@ -65,12 +66,9 @@ public class ComponentOptions { // results they want, which is their loss. opts.setDefusable(true); - boolean pendingIntentBalAllowedIsSetExplicitly = - opts.containsKey(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED); - if (pendingIntentBalAllowedIsSetExplicitly) { - mPendingIntentBalAllowed = - opts.getBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED); - } + mPendingIntentBalAllowed = + opts.getInt(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, + MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED); setPendingIntentBackgroundActivityLaunchAllowedByPermission( opts.getBoolean( KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, false)); @@ -85,7 +83,8 @@ public class ComponentOptions { * @hide */ @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) { - mPendingIntentBalAllowed = allowed; + mPendingIntentBalAllowed = allowed ? MODE_BACKGROUND_ACTIVITY_START_ALLOWED + : MODE_BACKGROUND_ACTIVITY_START_DENIED; } /** @@ -98,11 +97,8 @@ public class ComponentOptions { * @hide */ @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed() { - if (mPendingIntentBalAllowed == null) { - // cannot return null, so return the value used up to API level 33 for compatibility - return true; - } - return mPendingIntentBalAllowed; + // cannot return all detail, so return the value used up to API level 33 for compatibility + return mPendingIntentBalAllowed != MODE_BACKGROUND_ACTIVITY_START_DENIED; } /** @@ -119,16 +115,15 @@ public class ComponentOptions { @BackgroundActivityStartMode int state) { switch (state) { case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED: - mPendingIntentBalAllowed = null; - break; - case MODE_BACKGROUND_ACTIVITY_START_ALLOWED: - mPendingIntentBalAllowed = true; - break; case MODE_BACKGROUND_ACTIVITY_START_DENIED: - mPendingIntentBalAllowed = false; + case MODE_BACKGROUND_ACTIVITY_START_COMPAT: + case MODE_BACKGROUND_ACTIVITY_START_ALLOWED: + mPendingIntentBalAllowed = state; break; default: - throw new IllegalArgumentException(state + " is not valid"); + // Assume that future values are some variant of allowing the start. + mPendingIntentBalAllowed = MODE_BACKGROUND_ACTIVITY_START_ALLOWED; + break; } return this; } @@ -141,13 +136,7 @@ public class ComponentOptions { * @see #setPendingIntentBackgroundActivityStartMode(int) */ public @BackgroundActivityStartMode int getPendingIntentBackgroundActivityStartMode() { - if (mPendingIntentBalAllowed == null) { - return MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; - } else if (mPendingIntentBalAllowed) { - return MODE_BACKGROUND_ACTIVITY_START_ALLOWED; - } else { - return MODE_BACKGROUND_ACTIVITY_START_DENIED; - } + return mPendingIntentBalAllowed; } /** @@ -170,8 +159,8 @@ public class ComponentOptions { /** @hide */ public Bundle toBundle() { Bundle b = new Bundle(); - if (mPendingIntentBalAllowed != null) { - b.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, mPendingIntentBalAllowed); + if (mPendingIntentBalAllowed != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED) { + b.putInt(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, mPendingIntentBalAllowed); } if (mPendingIntentBalAllowedByPermission) { b.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java index b074e8b0c31b..2e252c12c51d 100644 --- a/core/java/android/content/IntentSender.java +++ b/core/java/android/content/IntentSender.java @@ -60,6 +60,10 @@ import android.util.AndroidException; * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}. */ public class IntentSender implements Parcelable { + private static final Bundle SEND_INTENT_DEFAULT_OPTIONS = + ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT).toBundle(); + @UnsupportedAppUsage private final IIntentSender mTarget; IBinder mWhitelistToken; @@ -161,7 +165,8 @@ public class IntentSender implements Parcelable { */ public void sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler) throws SendIntentException { - sendIntent(context, code, intent, onFinished, handler, null, null /* options */); + sendIntent(context, code, intent, onFinished, handler, null, + SEND_INTENT_DEFAULT_OPTIONS); } /** @@ -194,7 +199,7 @@ public class IntentSender implements Parcelable { OnFinished onFinished, Handler handler, String requiredPermission) throws SendIntentException { sendIntent(context, code, intent, onFinished, handler, requiredPermission, - null /* options */); + SEND_INTENT_DEFAULT_OPTIONS); } /** diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index da45a7727faf..8d7a1c9f8228 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -18,6 +18,10 @@ package com.android.server.am; import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManager.START_SUCCESS; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -389,13 +393,20 @@ public final class PendingIntentRecord extends IIntentSender.Stub { private static BackgroundStartPrivileges getBackgroundStartPrivilegesAllowedByCaller( @Nullable Bundle options, int callingUid, @Nullable String callingPackage) { - if (options == null || !options.containsKey( - ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED)) { + if (options == null) { return getDefaultBackgroundStartPrivileges(callingUid, callingPackage); } - return options.getBoolean(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED) - ? BackgroundStartPrivileges.ALLOW_BAL - : BackgroundStartPrivileges.NONE; + switch (options.getInt(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, + MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED)) { + case MODE_BACKGROUND_ACTIVITY_START_DENIED: + return BackgroundStartPrivileges.NONE; + case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED: + return getDefaultBackgroundStartPrivileges(callingUid, callingPackage); + case MODE_BACKGROUND_ACTIVITY_START_ALLOWED: + case MODE_BACKGROUND_ACTIVITY_START_COMPAT: + default: + return BackgroundStartPrivileges.ALLOW_BAL; + } } /** diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index eb1f3b402364..04f75c9463c1 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityOptions.BackgroundActivityStartMode; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; @@ -105,6 +106,7 @@ public class BackgroundActivityStartController { static final String AUTO_OPT_IN_NOT_PENDING_INTENT = "notPendingIntent"; static final String AUTO_OPT_IN_CALL_FOR_RESULT = "callForResult"; static final String AUTO_OPT_IN_SAME_UID = "sameUid"; + static final String AUTO_OPT_IN_COMPAT = "compatibility"; /** If enabled the creator will not allow BAL on its behalf by default. */ @ChangeId @@ -303,6 +305,10 @@ public class BackgroundActivityStartController { } else if (callingUid == realCallingUid && !balRequireOptInSameUid()) { mAutoOptInReason = AUTO_OPT_IN_SAME_UID; mAutoOptInCaller = false; + } else if (realCallerBackgroundActivityStartMode + == MODE_BACKGROUND_ACTIVITY_START_COMPAT) { + mAutoOptInReason = AUTO_OPT_IN_COMPAT; + mAutoOptInCaller = false; } else { mAutoOptInReason = null; mAutoOptInCaller = false; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java index 37e0818eb083..5787780cef46 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java @@ -24,6 +24,8 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; @@ -250,6 +252,7 @@ public class ActivityOptionsTest { case ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN: case ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN: case ActivityOptions.KEY_TRANSIENT_LAUNCH: + case ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED: case "android:activity.animationFinishedListener": // KEY_ANIMATION_FINISHED_LISTENER case "android:activity.animSpecs": // KEY_ANIM_SPECS @@ -319,7 +322,7 @@ public class ActivityOptionsTest { Log.e("ActivityOptionsTests", "Unknown key " + key + " is found. " + "Please review if the given bundle should be protected with permissions."); } - assertTrue(unknownKeys.isEmpty()); + assertThat(unknownKeys).isEmpty(); } public static class TrampolineActivity extends Activity { |