From 64c8239c8541fe03c9811caf7931c1c574fa7c80 Mon Sep 17 00:00:00 2001 From: Achim Thesmann Date: Thu, 5 Jan 2023 16:45:33 -0800 Subject: [PATCH] Allow a PendingIntent's creator to revoke BAL privilege. Currently if the creator of a PendingIntent is allowed to start a background activity the PendingIntent has the same privilege even if started by another process in the background that does not have this permission. This change allows creators to opt out of this behavior. Nothing changes if the creator does not actively opt out. Test: atest com.android.server.wm.ActivityStarterTests Bug: 261780465 Change-Id: I29db44d4fb07fa4a178a0d2e5822f655cfa56c39 --- core/api/current.txt | 2 + core/java/android/app/ActivityOptions.java | 53 +++++++++++++------ .../wm/BackgroundActivityStartController.java | 4 +- .../server/wm/SafeActivityOptions.java | 4 +- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 8d27311f729ae..ca6a387e964c7 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -4756,6 +4756,7 @@ package android.app { method public int getLaunchDisplayId(); method public boolean getLockTaskMode(); method public int getPendingIntentBackgroundActivityStartMode(); + method public int getPendingIntentCreatorBackgroundActivityStartMode(); method public int getSplashScreenStyle(); method @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed(); method public boolean isShareIdentityEnabled(); @@ -4776,6 +4777,7 @@ package android.app { method public android.app.ActivityOptions setLockTaskEnabled(boolean); method @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean); method @NonNull public android.app.ActivityOptions setPendingIntentBackgroundActivityStartMode(int); + method @NonNull public android.app.ActivityOptions setPendingIntentCreatorBackgroundActivityStartMode(int); method @NonNull public android.app.ActivityOptions setShareIdentityEnabled(boolean); method @NonNull public android.app.ActivityOptions setSplashScreenStyle(int); method public android.os.Bundle toBundle(); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 2a390a7dbb51d..aa53e38262c3f 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -387,8 +387,8 @@ public class ActivityOptions extends ComponentOptions { /** See {@link #setDismissKeyguard()}. */ private static final String KEY_DISMISS_KEYGUARD = "android.activity.dismissKeyguard"; - private static final String KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE = - "android.activity.ignorePendingIntentCreatorForegroundState"; + private static final String KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE = + "android.activity.pendingIntentCreatorBackgroundActivityStartMode"; /** * @see #setLaunchCookie @@ -489,7 +489,9 @@ public class ActivityOptions extends ComponentOptions { private boolean mTransientLaunch; private PictureInPictureParams mLaunchIntoPipParams; private boolean mDismissKeyguard; - private boolean mIgnorePendingIntentCreatorForegroundState; + @BackgroundActivityStartMode + private int mPendingIntentCreatorBackgroundActivityStartMode = + MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED; private boolean mDisableStartingWindow; /** @@ -1297,8 +1299,9 @@ public class ActivityOptions extends ComponentOptions { mIsEligibleForLegacyPermissionPrompt = opts.getBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE); mDismissKeyguard = opts.getBoolean(KEY_DISMISS_KEYGUARD); - mIgnorePendingIntentCreatorForegroundState = opts.getBoolean( - KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE); + mPendingIntentCreatorBackgroundActivityStartMode = opts.getInt( + KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE, + MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED); mDisableStartingWindow = opts.getBoolean(KEY_DISABLE_STARTING_WINDOW); } @@ -1999,19 +2002,38 @@ public class ActivityOptions extends ComponentOptions { * Sets background activity launch logic won't use pending intent creator foreground state. * * @hide + * @deprecated use {@link #setPendingIntentCreatorBackgroundActivityStartMode(int)} instead */ - public ActivityOptions setIgnorePendingIntentCreatorForegroundState(boolean state) { - mIgnorePendingIntentCreatorForegroundState = state; + @Deprecated + public ActivityOptions setIgnorePendingIntentCreatorForegroundState(boolean ignore) { + mPendingIntentCreatorBackgroundActivityStartMode = ignore + ? MODE_BACKGROUND_ACTIVITY_START_DENIED : MODE_BACKGROUND_ACTIVITY_START_ALLOWED; return this; } /** - * @return whether background activity launch logic should use pending intent creator - * foreground state. - * @hide + * Allow a {@link PendingIntent} to use the privilege of its creator to start background + * activities. + * + * @param mode the {@link android.app.ComponentOptions.BackgroundActivityStartMode} being set + * @throws IllegalArgumentException is the value is not a valid + * {@link android.app.ComponentOptions.BackgroundActivityStartMode} */ - public boolean getIgnorePendingIntentCreatorForegroundState() { - return mIgnorePendingIntentCreatorForegroundState; + @NonNull + public ActivityOptions setPendingIntentCreatorBackgroundActivityStartMode( + @BackgroundActivityStartMode int mode) { + mPendingIntentCreatorBackgroundActivityStartMode = mode; + return this; + } + + /** + * Returns the mode to start background activities granted by the creator of the + * {@link PendingIntent}. + * + * @return the {@link android.app.ComponentOptions.BackgroundActivityStartMode} currently set + */ + public @BackgroundActivityStartMode int getPendingIntentCreatorBackgroundActivityStartMode() { + return mPendingIntentCreatorBackgroundActivityStartMode; } /** @@ -2285,9 +2307,10 @@ public class ActivityOptions extends ComponentOptions { if (mDismissKeyguard) { b.putBoolean(KEY_DISMISS_KEYGUARD, mDismissKeyguard); } - if (mIgnorePendingIntentCreatorForegroundState) { - b.putBoolean(KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE, - mIgnorePendingIntentCreatorForegroundState); + if (mPendingIntentCreatorBackgroundActivityStartMode + != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED) { + b.putInt(KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE, + mPendingIntentCreatorBackgroundActivityStartMode); } if (mDisableStartingWindow) { b.putBoolean(KEY_DISABLE_STARTING_WINDOW, mDisableStartingWindow); diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index cd79f2ecbe79a..e1fdeca167daf 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.BackgroundStartPrivileges; +import android.app.ComponentOptions; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; @@ -166,7 +167,8 @@ public class BackgroundActivityStartController { final boolean useCallingUidState = originatingPendingIntent == null || checkedOptions == null - || !checkedOptions.getIgnorePendingIntentCreatorForegroundState(); + || checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() + != ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; if (useCallingUidState) { if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java index 98ca9aecc7067..586077658a262 100644 --- a/services/core/java/com/android/server/wm/SafeActivityOptions.java +++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java @@ -146,8 +146,8 @@ public class SafeActivityOptions { .setLaunchRootTask(options.getLaunchRootTask()) .setPendingIntentBackgroundActivityStartMode( options.getPendingIntentBackgroundActivityStartMode()) - .setIgnorePendingIntentCreatorForegroundState( - options.getIgnorePendingIntentCreatorForegroundState()); + .setPendingIntentCreatorBackgroundActivityStartMode( + options.getPendingIntentCreatorBackgroundActivityStartMode()); } /**