Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8a05514 authored by Ricky Wai's avatar Ricky Wai
Browse files

Add hidden flag in ActivityOptions to ignore PendingIntent creator foreground state

Bug: 227431919
Test: atest BackgroundActivityLaunchTest
Change-Id: I7192f65e747e6048d3a26ecb203767290fa5406e
parent acf4d5a8
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -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;
    }

+5 −1
Original line number Diff line number Diff line
@@ -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);
+5 −1
Original line number Diff line number Diff line
@@ -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(
+72 −58
Original line number Diff line number Diff line
@@ -1268,10 +1268,15 @@ class ActivityStarter {
            boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions) {
        // don't abort for the most important UIDs
        final int callingAppId = UserHandle.getAppId(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 + ")");
                    Slog.d(TAG,
                            "Activity start allowed for important callingUid (" + callingUid + ")");
                }
                return false;
            }
@@ -1279,7 +1284,8 @@ class ActivityStarter {
            // 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 + ")");
                    Slog.d(TAG,
                            "Activity start allowed for home app callingUid (" + callingUid + ")");
                }
                return false;
            }
@@ -1292,6 +1298,7 @@ class ActivityStarter {
                }
                return false;
            }
        }

        // This is used to block background activity launch even if the app is still
        // visible to user after user clicking home button.
@@ -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,8 +1409,10 @@ class ActivityStarter {
                return false;
            }
        }
        if (useCallingUidState) {
            // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
        if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
            if (mService.checkPermission(
                    START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                    == PERMISSION_GRANTED) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG,
@@ -1429,7 +1440,8 @@ class ActivityStarter {
            }
            // don't abort if the callingUid has companion device
            final int callingUserId = UserHandle.getUserId(callingUid);
        if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
            if (mService.isAssociatedCompanionApp(callingUserId,
                    callingUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
                            + ") is companion app");
@@ -1437,11 +1449,13 @@ class ActivityStarter {
                return false;
            }
            // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
        if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
            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
        // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
@@ -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) {