Add hidden flag in ActivityOptions to ignore PendingIntent creator foreground state

Bug: 227431919
Test: atest BackgroundActivityLaunchTest
Change-Id: I7192f65e747e6048d3a26ecb203767290fa5406e
This commit is contained in:
Ricky Wai
2022-03-30 15:30:58 +00:00
parent acf4d5a89d
commit b8a05514f7
4 changed files with 109 additions and 60 deletions

View File

@@ -365,6 +365,9 @@ public class ActivityOptions extends ComponentOptions {
private static final String KEY_DISMISS_KEYGUARD_IF_INSECURE =
"android.activity.dismissKeyguardIfInsecure";
private static final String KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE =
"android.activity.ignorePendingIntentCreatorForegroundState";
/**
* @see #setLaunchCookie
* @hide
@@ -462,6 +465,7 @@ public class ActivityOptions extends ComponentOptions {
private boolean mTransientLaunch;
private PictureInPictureParams mLaunchIntoPipParams;
private boolean mDismissKeyguardIfInsecure;
private boolean mIgnorePendingIntentCreatorForegroundState;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -1260,6 +1264,8 @@ public class ActivityOptions extends ComponentOptions {
mIsEligibleForLegacyPermissionPrompt =
opts.getBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE);
mDismissKeyguardIfInsecure = opts.getBoolean(KEY_DISMISS_KEYGUARD_IF_INSECURE);
mIgnorePendingIntentCreatorForegroundState = opts.getBoolean(
KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE);
}
/**
@@ -1876,6 +1882,23 @@ public class ActivityOptions extends ComponentOptions {
return mDismissKeyguardIfInsecure;
}
/**
* Sets background activity launch logic won't use pending intent creator foreground state.
* @hide
*/
public void setIgnorePendingIntentCreatorForegroundState(boolean state) {
mIgnorePendingIntentCreatorForegroundState = state;
}
/**
* @return whether background activity launch logic should use pending intent creator
* foreground state.
* @hide
*/
public boolean getIgnorePendingIntentCreatorForegroundState() {
return mIgnorePendingIntentCreatorForegroundState;
}
/**
* Update the current values in this ActivityOptions from those supplied
* in <var>otherOptions</var>. Any values
@@ -2140,6 +2163,10 @@ public class ActivityOptions extends ComponentOptions {
if (mDismissKeyguardIfInsecure) {
b.putBoolean(KEY_DISMISS_KEYGUARD_IF_INSECURE, mDismissKeyguardIfInsecure);
}
if (mIgnorePendingIntentCreatorForegroundState) {
b.putBoolean(KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE,
mIgnorePendingIntentCreatorForegroundState);
}
return b;
}

View File

@@ -26,6 +26,7 @@ import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -970,13 +971,16 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
intent.setComponent(provider.getInfoLocked(mContext).configure);
intent.setFlags(secureFlags);
final ActivityOptions options = ActivityOptions.makeBasic();
options.setIgnorePendingIntentCreatorForegroundState(true);
// All right, create the sender.
final long identity = Binder.clearCallingIdentity();
try {
return PendingIntent.getActivityAsUser(
mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
null, new UserHandle(provider.getUserId()))
options.toBundle(), new UserHandle(provider.getUserId()))
.getIntentSender();
} finally {
Binder.restoreCallingIdentity(identity);

View File

@@ -55,6 +55,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.AnrController;
import android.app.AppOpsManager;
import android.app.IActivityManager;
@@ -3528,9 +3529,12 @@ class StorageManagerService extends IStorageManager.Stub
appInfo.manageSpaceActivityName);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
final ActivityOptions options = ActivityOptions.makeBasic();
options.setIgnorePendingIntentCreatorForegroundState(true);
PendingIntent activity = PendingIntent.getActivity(targetAppContext, requestCode,
intent,
FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE);
FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE, options.toBundle());
return activity;
} catch (PackageManager.NameNotFoundException e) {
throw new IllegalArgumentException(

View File

@@ -1268,29 +1268,36 @@ class ActivityStarter {
boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions) {
// don't abort for the most important UIDs
final int callingAppId = UserHandle.getAppId(callingUid);
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
|| callingAppId == Process.NFC_UID) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed for important callingUid (" + callingUid + ")");
final boolean useCallingUidState =
originatingPendingIntent == null || checkedOptions == null
|| !checkedOptions.getIgnorePendingIntentCreatorForegroundState();
if (useCallingUidState) {
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
|| callingAppId == Process.NFC_UID) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG,
"Activity start allowed for important callingUid (" + callingUid + ")");
}
return false;
}
return false;
}
// Always allow home application to start activities.
if (isHomeApp(callingUid, callingPackage)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed for home app callingUid (" + callingUid + ")");
// Always allow home application to start activities.
if (isHomeApp(callingUid, callingPackage)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG,
"Activity start allowed for home app callingUid (" + callingUid + ")");
}
return false;
}
return false;
}
// IME should always be allowed to start activity, like IME settings.
final WindowState imeWindow = mRootWindowContainer.getCurrentInputMethodWindow();
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed for active ime (" + callingUid + ")");
// IME should always be allowed to start activity, like IME settings.
final WindowState imeWindow = mRootWindowContainer.getCurrentInputMethodWindow();
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed for active ime (" + callingUid + ")");
}
return false;
}
return false;
}
// This is used to block background activity launch even if the app is still
@@ -1310,9 +1317,11 @@ class ActivityStarter {
// is allowed, or apps like live wallpaper with non app visible window will be allowed.
final boolean appSwitchAllowedOrFg =
appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
if (((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
final boolean allowCallingUidStartActivity =
((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
&& callingUidHasAnyVisibleWindow)
|| isCallingUidPersistentSystemProcess) {
|| isCallingUidPersistentSystemProcess;
if (useCallingUidState && allowCallingUidStartActivity) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed: callingUidHasAnyVisibleWindow = " + callingUid
+ ", isCallingUidPersistentSystemProcess = "
@@ -1400,47 +1409,52 @@ class ActivityStarter {
return false;
}
}
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
== PERMISSION_GRANTED) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG,
"Background activity start allowed: START_ACTIVITIES_FROM_BACKGROUND "
+ "permission granted for uid "
+ callingUid);
if (useCallingUidState) {
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (mService.checkPermission(
START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
== PERMISSION_GRANTED) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG,
"Background activity start allowed: START_ACTIVITIES_FROM_BACKGROUND "
+ "permission granted for uid "
+ callingUid);
}
return false;
}
return false;
}
// don't abort if the caller has the same uid as the recents component
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
+ ") is recents");
// don't abort if the caller has the same uid as the recents component
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
+ ") is recents");
}
return false;
}
return false;
}
// don't abort if the callingUid is the device owner
if (mService.isDeviceOwner(callingUid)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
+ ") is device owner");
// don't abort if the callingUid is the device owner
if (mService.isDeviceOwner(callingUid)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
+ ") is device owner");
}
return false;
}
return false;
}
// don't abort if the callingUid has companion device
final int callingUserId = UserHandle.getUserId(callingUid);
if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
+ ") is companion app");
// don't abort if the callingUid has companion device
final int callingUserId = UserHandle.getUserId(callingUid);
if (mService.isAssociatedCompanionApp(callingUserId,
callingUid)) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
+ ") is companion app");
}
return false;
}
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
if (mService.hasSystemAlertWindowPermission(callingUid,
callingPid, callingPackage)) {
Slog.w(TAG, "Background activity start for " + callingPackage
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
return false;
}
return false;
}
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
Slog.w(TAG, "Background activity start for " + callingPackage
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
return false;
}
// If we don't have callerApp at this point, no caller was provided to startActivity().
// That's the case for PendingIntent-based starts, since the creator's process might not be
@@ -1452,7 +1466,7 @@ class ActivityStarter {
callerAppUid = realCallingUid;
}
// don't abort if the callerApp or other processes of that uid are allowed in any way
if (callerApp != null) {
if (callerApp != null && useCallingUidState) {
// first check the original calling process
if (callerApp.areBackgroundActivityStartsAllowed(appSwitchState)) {
if (DEBUG_ACTIVITY_STARTS) {