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

Commit 1933dcbb authored by Achim Thesmann's avatar Achim Thesmann Committed by MSe1969
Browse files

RESTRICT AUTOMERGE Ignore pinned Windows (Consolidated fix)

ag/32704936
ag/35782210
ag/36195227
ag/36359572

Bug: 439984935
Test: atest BackgroundActivityLaunchTest
Flag: EXEMPT BUGFIX
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:d7e9d1e8b8fd3202dfc8a91772ae7c7d1e88e2c8
Merged-In: I9ce93366a0876c7bc594ef818c8598342d70513d
Change-Id: I9ce93366a0876c7bc594ef818c8598342d70513d
parent e0853063
Loading
Loading
Loading
Loading
+48 −16
Original line number Diff line number Diff line
@@ -239,7 +239,9 @@ public class BackgroundActivityStartController {
        private final int mCallingUid;
        private final int mCallingPid;
        private final @ActivityTaskManagerService.AppSwitchState int mAppSwitchState;
        private final boolean mCallingUidHasAnyVisibleWindow;
        private final boolean mCallingUidHasVisibleActivity;
        private final boolean mCallingUidHasVisibleNotPinnedActivity;
        private final boolean mCallingUidHasNonAppVisibleWindow;
        private final @ActivityManager.ProcessState int mCallingUidProcState;
        private final boolean mIsCallingUidPersistentSystemProcess;
        final BackgroundStartPrivileges mBalAllowedByPiSender;
@@ -248,7 +250,9 @@ public class BackgroundActivityStartController {
        private final String mRealCallingPackage;
        private final int mRealCallingUid;
        private final int mRealCallingPid;
        private final boolean mRealCallingUidHasAnyVisibleWindow;
        private final boolean mRealCallingUidHasVisibleActivity;
        private final boolean mRealCallingUidHasVisibleNotPinnedActivity;
        private final boolean mRealCallingUidHasNonAppVisibleWindow;
        private final @ActivityManager.ProcessState int mRealCallingUidProcState;
        private final boolean mIsRealCallingUidPersistentSystemProcess;
        private final PendingIntentRecord mOriginatingPendingIntent;
@@ -343,16 +347,25 @@ public class BackgroundActivityStartController {
            mCallingUidProcState = mService.mActiveUids.getUidState(callingUid);
            mIsCallingUidPersistentSystemProcess =
                    mCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
            mCallingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
            mCallingUidHasVisibleActivity =
                    mService.mVisibleActivityProcessTracker.hasVisibleActivity(callingUid);
            mCallingUidHasVisibleNotPinnedActivity = mService.mVisibleActivityProcessTracker
                    .hasVisibleNotPinnedActivity(callingUid);
            mCallingUidHasNonAppVisibleWindow = mService.mActiveUids.hasNonAppVisibleWindow(
                    callingUid);
            if (realCallingUid == NO_PROCESS_UID) {
                // no process provided
                mRealCallingUidProcState = PROCESS_STATE_NONEXISTENT;
                mRealCallingUidHasAnyVisibleWindow = false;
                mRealCallingUidHasVisibleActivity = false;
                mRealCallingUidHasNonAppVisibleWindow = false;
                mRealCallingUidHasVisibleNotPinnedActivity = false;
                mRealCallerApp = null;
                mIsRealCallingUidPersistentSystemProcess = false;
            } else if (callingUid == realCallingUid) {
                mRealCallingUidProcState = mCallingUidProcState;
                mRealCallingUidHasAnyVisibleWindow = mCallingUidHasAnyVisibleWindow;
                mRealCallingUidHasVisibleActivity = mCallingUidHasVisibleActivity;
                mRealCallingUidHasVisibleNotPinnedActivity = mCallingUidHasVisibleNotPinnedActivity;
                mRealCallingUidHasNonAppVisibleWindow = mCallingUidHasNonAppVisibleWindow;
                // In the PendingIntent case callerApp is not passed in, so resolve it ourselves.
                mRealCallerApp = callerApp == null
                        ? mService.getProcessController(realCallingPid, realCallingUid)
@@ -360,8 +373,14 @@ public class BackgroundActivityStartController {
                mIsRealCallingUidPersistentSystemProcess = mIsCallingUidPersistentSystemProcess;
            } else {
                mRealCallingUidProcState = mService.mActiveUids.getUidState(realCallingUid);
                mRealCallingUidHasAnyVisibleWindow =
                        mService.hasActiveVisibleWindow(realCallingUid);
                mRealCallingUidHasVisibleActivity =
                        mService.mVisibleActivityProcessTracker.hasVisibleActivity(
                                realCallingUid);
                mRealCallingUidHasVisibleNotPinnedActivity =
                        mService.mVisibleActivityProcessTracker.hasVisibleNotPinnedActivity(
                                realCallingUid);
                mRealCallingUidHasNonAppVisibleWindow =
                        mService.mActiveUids.hasNonAppVisibleWindow(realCallingUid);
                mRealCallerApp = mService.getProcessController(realCallingPid, realCallingUid);
                mIsRealCallingUidPersistentSystemProcess =
                        mRealCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
@@ -458,7 +477,11 @@ public class BackgroundActivityStartController {
            sb.append("; callingUid: ").append(mCallingUid);
            sb.append("; callingPid: ").append(mCallingPid);
            sb.append("; appSwitchState: ").append(mAppSwitchState);
            sb.append("; callingUidHasAnyVisibleWindow: ").append(mCallingUidHasAnyVisibleWindow);
            sb.append("; callingUidHasVisibleActivity: ").append(mCallingUidHasVisibleActivity);
            sb.append("; callingUidHasVisibleNotPinnedActivity: ")
                    .append(mCallingUidHasVisibleNotPinnedActivity);
            sb.append("; callingUidHasNonAppVisibleWindow: ").append(
                    mCallingUidHasNonAppVisibleWindow);
            sb.append("; callingUidProcState: ").append(DebugUtils.valueToString(
                    ActivityManager.class, "PROCESS_STATE_", mCallingUidProcState));
            sb.append("; isCallingUidPersistentSystemProcess: ")
@@ -484,8 +507,12 @@ public class BackgroundActivityStartController {
                        .append(getTargetSdk(mRealCallingPackage));
                sb.append("; realCallingUid: ").append(mRealCallingUid);
                sb.append("; realCallingPid: ").append(mRealCallingPid);
                sb.append("; realCallingUidHasAnyVisibleWindow: ")
                        .append(mRealCallingUidHasAnyVisibleWindow);
                sb.append("; realCallingUidHasVisibleActivity: ")
                        .append(mRealCallingUidHasVisibleActivity);
                sb.append("; realCallingUidHasVisibleNotPinnedActivity: ")
                        .append(mRealCallingUidHasVisibleNotPinnedActivity);
                sb.append("; realCallingUidHasNonAppVisibleWindow: ")
                        .append(mRealCallingUidHasNonAppVisibleWindow);
                sb.append("; realCallingUidProcState: ").append(DebugUtils.valueToString(
                        ActivityManager.class, "PROCESS_STATE_", mRealCallingUidProcState));
                sb.append("; isRealCallingUidPersistentSystemProcess: ")
@@ -567,6 +594,10 @@ public class BackgroundActivityStartController {
        /** indicates that this verdict is based on the real calling UID and not the calling UID */
        private boolean mBasedOnRealCaller;

        BalVerdict(@BalCode int balCode, String message) {
            this(balCode, true, message);
        }

        BalVerdict(@BalCode int balCode, boolean background, String message) {
            this.mBackground = background;
            this.mCode = balCode;
@@ -847,9 +878,9 @@ public class BackgroundActivityStartController {
        // 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 && state.mCallingUidHasAnyVisibleWindow) {
        if (appSwitchAllowedOrFg && state.mCallingUidHasVisibleNotPinnedActivity) {
            return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                    /*background*/ false, "callingUid has visible window");
                    "callingUid has visible non-pinned window");
        }
        if (mService.mActiveUids.hasNonAppVisibleWindow(callingUid)) {
            return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
@@ -943,7 +974,7 @@ public class BackgroundActivityStartController {
                || state.mAppSwitchState == APP_SWITCH_FG_ONLY
                || isHomeApp(state.mRealCallingUid, state.mRealCallingPackage);
        if (balImproveRealCallerVisibilityCheck()) {
            if (appSwitchAllowedOrFg && state.mRealCallingUidHasAnyVisibleWindow) {
            if (appSwitchAllowedOrFg && state.mRealCallingUidHasVisibleNotPinnedActivity) {
                return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                        /*background*/ false, "realCallingUid has visible window");
            }
@@ -954,7 +985,8 @@ public class BackgroundActivityStartController {
        } else {
            // don't abort if the realCallingUid has a visible window
            // TODO(b/171459802): We should check appSwitchAllowed also
            if (state.mRealCallingUidHasAnyVisibleWindow) {
            if (state.mRealCallingUidHasVisibleNotPinnedActivity
                    || mService.mActiveUids.hasNonAppVisibleWindow(state.mRealCallingUid)) {
                return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                        /*background*/ false,
                        "realCallingUid has visible (non-toast) window.");
@@ -1660,10 +1692,10 @@ public class BackgroundActivityStartController {
                            state.mCallingUid,
                            state.mCallingPackage,
                            state.mCallingUidProcState,
                            state.mCallingUidHasAnyVisibleWindow,
                            state.mCallingUidHasVisibleActivity,
                            state.mRealCallingUid,
                            state.mRealCallingUidProcState,
                            state.mRealCallingUidHasAnyVisibleWindow,
                            state.mRealCallingUidHasVisibleActivity,
                            (state.mOriginatingPendingIntent != null));
        }

+7 −4
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@ class BackgroundLaunchProcessController {
    BalVerdict areBackgroundActivityStartsAllowed(
            int pid, int uid, String packageName,
            int appSwitchState, boolean isCheckingForFgsStart,
            boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges,
            boolean hasActivityInVisibleTask, boolean inPinnedWindow,
            boolean hasBackgroundActivityStartPrivileges,
            long lastStopAppSwitchesTime, long lastActivityLaunchTime,
            long lastActivityFinishTime) {
        // Allow if the proc is instrumenting with background activity starts privs.
@@ -123,9 +124,11 @@ class BackgroundLaunchProcessController {
            return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, /*background*/ false,
                    "process bound by foreground uid");
        }
        // Allow if the caller has an activity in any foreground task.
        if (hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) {
            return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ false,
        // Allow if the caller has an activity in any foreground task, unless it's a pinned window
        // and not a foreground service start.
        if ((isCheckingForFgsStart || !inPinnedWindow)
                && hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) {
            return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/
                    "process has activity in foreground task");
        }

+10 −2
Original line number Diff line number Diff line
@@ -81,14 +81,22 @@ class VisibleActivityProcessTracker {
     * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true.
     */
    boolean hasVisibleActivity(int uid) {
        return match(uid, null /* predicate */);
        return match(uid, ALWAYS_TRUE);
    }

    /**
     * Returns {@code true} if the uid has a process that contains an activity with
     * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true.
     */
    boolean hasVisibleNotPinnedActivity(int uid) {
        return match(uid, wpc -> wpc.hasVisibleNotPinnedActivity());
    }

    private boolean match(int uid, Predicate<WindowProcessController> predicate) {
        synchronized (mProcMap) {
            for (int i = mProcMap.size() - 1; i >= 0; i--) {
                final WindowProcessController wpc = mProcMap.keyAt(i);
                if (wpc.mUid == uid && (predicate == null || predicate.test(wpc))) {
                if (wpc.mUid == uid && predicate.test(wpc)) {
                    return true;
                }
            }
+17 −1
Original line number Diff line number Diff line
@@ -665,7 +665,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
            int appSwitchState, boolean isCheckingForFgsStart) {
        return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid,
                mInfo.packageName, appSwitchState, isCheckingForFgsStart,
                hasActivityInVisibleTask(), mInstrumentingWithBackgroundActivityStartPrivileges,
                hasActivityInVisibleTask(), inPinnedWindowingMode(),
                mInstrumentingWithBackgroundActivityStartPrivileges,
                mAtm.getLastStopAppSwitchesTime(),
                mLastActivityLaunchTime, mLastActivityFinishTime);
    }
@@ -834,6 +835,21 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        return mHasActivities || mHasRecentTasks;
    }

    /**
     * Check if any Activity is visible (or visibility requested) and not pinned.
     */
    boolean hasVisibleNotPinnedActivity() {
        if (!hasVisibleActivities()) return false;
        for (int i = mActivities.size() - 1; i >= 0; --i) {
            final ActivityRecord activityRecord = mActivities.get(i);
            if ((activityRecord.isVisible() || activityRecord.isVisibleRequested())
                    && !activityRecord.inPinnedWindowingMode()) {
                return true;
            }
        }
        return false;
    }

    @Nullable
    TaskDisplayArea getTopActivityDisplayArea() {
        if (mActivities.isEmpty()) {
+14 −6
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ public class BackgroundActivityStartControllerTests {
    AppOpsManager mAppOpsManager;
    MirrorActiveUids mActiveUids = new MirrorActiveUids();
    WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap();
    @Mock
    VisibleActivityProcessTracker mVisibleActivityProcessTracker;

    @Mock
    ActivityTaskSupervisor mSupervisor;
@@ -184,6 +186,8 @@ public class BackgroundActivityStartControllerTests {
        mService.mRootWindowContainer = mRootWindowContainer;
        Mockito.when(mService.getAppOpsManager()).thenReturn(mAppOpsManager);
        setViaReflection(mService, "mProcessMap", mProcessMap);
        setViaReflection(mService, "mVisibleActivityProcessTracker",
                mVisibleActivityProcessTracker);

        //Mockito.when(mSupervisor.getBackgroundActivityLaunchController()).thenReturn(mController);
        setViaReflection(mSupervisor, "mRecentTasks", mRecentTasks);
@@ -506,8 +510,9 @@ public class BackgroundActivityStartControllerTests {
        assertThat(balState.realCallerExplicitOptInOrOut()).isFalse();
        assertThat(balState.toString()).isEqualTo(
                "[callingPackage: package.app1; callingPackageTargetSdk: -1; callingUid: 10001; "
                        + "callingPid: 11001; appSwitchState: 0; "
                        + "callingUidHasAnyVisibleWindow: false; callingUidProcState: NONEXISTENT; "
                        + "callingPid: 11001; appSwitchState: 0; callingUidHasVisibleActivity: "
                        + "false; callingUidHasVisibleNotPinnedActivity: false; "
                        + "callingUidHasNonAppVisibleWindow: false; callingUidProcState: NONEXISTENT; "
                        + "isCallingUidPersistentSystemProcess: false; forcedBalByPiSender: BSP"
                        + ".NONE; intent: Intent { cmp=package.app3/someClass }; callerApp: "
                        + "mCallerApp; inVisibleTask: false; balAllowedByPiCreator: BSP"
@@ -590,8 +595,9 @@ public class BackgroundActivityStartControllerTests {
        assertThat(balState.realCallerExplicitOptInOrOut()).isFalse();
        assertThat(balState.toString()).isEqualTo(
                "[callingPackage: package.app1; callingPackageTargetSdk: -1; callingUid: 10001; "
                        + "callingPid: 11001; appSwitchState: 0; "
                        + "callingUidHasAnyVisibleWindow: false; callingUidProcState: NONEXISTENT; "
                        + "callingPid: 11001; appSwitchState: 0; callingUidHasVisibleActivity: "
                        + "false; callingUidHasVisibleNotPinnedActivity: false; "
                        + "callingUidHasNonAppVisibleWindow: false; callingUidProcState: NONEXISTENT; "
                        + "isCallingUidPersistentSystemProcess: false; forcedBalByPiSender: BSP"
                        + ".NONE; intent: Intent { cmp=package.app3/someClass }; callerApp: "
                        + "mCallerApp; inVisibleTask: false; balAllowedByPiCreator: BSP"
@@ -600,7 +606,9 @@ public class BackgroundActivityStartControllerTests {
                        + "isCallForResult: false; isPendingIntent: true; autoOptInReason: "
                        + "null; realCallingPackage: uid=1[debugOnly]; "
                        + "realCallingPackageTargetSdk: -1; realCallingUid: 1; realCallingPid: 1;"
                        + " realCallingUidHasAnyVisibleWindow: false; realCallingUidProcState: "
                        + " realCallingUidHasVisibleActivity: false; "
                        + "realCallingUidHasVisibleNotPinnedActivity: false; "
                        + "realCallingUidHasNonAppVisibleWindow: false; realCallingUidProcState: "
                        + "NONEXISTENT; isRealCallingUidPersistentSystemProcess: false; "
                        + "originatingPendingIntent: PendingIntentRecord; realCallerApp: null; "
                        + "balAllowedByPiSender: BSP.ALLOW_FGS; resultIfPiSenderAllowsBal: null]");
Loading