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

Commit 245977cb authored by Ricky Wai's avatar Ricky Wai
Browse files

Do not allow pip window to start background single instance activity

Otherwise, the window will be recreated and shown in foreground

Bug: 170613407
Test: Fail to start a singleInstance activity in pip while the app is in background
Test: atest ActivityStarterTests#testBackgroundActivityStartsDisallowed_unsupportedStartsAborted
Change-Id: I21cb91ab544557a5c8a4a1515604fa8f5c7797bb
parent 9d29bba3
Loading
Loading
Loading
Loading
+8 −1
Original line number Original line Diff line number Diff line
@@ -1871,7 +1871,14 @@ class ActivityStarter {
            }
            }
        }
        }


        if (mRestrictedBgActivity && (newTask || !targetTask.isUidPresent(mCallingUid))
        // Do not allow background activity start in new task or in a task that uid is not present.
        // Also do not allow pinned window to start single instance activity in background,
        // as it will recreate the window and makes it to foreground.
        boolean blockBalInTask = (newTask
                || !targetTask.isUidPresent(mCallingUid)
                || (LAUNCH_SINGLE_INSTANCE == mLaunchMode && targetTask.inPinnedWindowingMode()));

        if (mRestrictedBgActivity && blockBalInTask
                && handleBackgroundActivityAbort(mStartActivity)) {
                && handleBackgroundActivityAbort(mStartActivity)) {
            Slog.e(TAG, "Abort background activity starts from " + mCallingUid);
            Slog.e(TAG, "Abort background activity starts from " + mCallingUid);
            return START_ABORTED;
            return START_ABORTED;
+48 −4
Original line number Original line Diff line number Diff line
@@ -31,12 +31,15 @@ import static android.app.ActivityManager.START_SWITCHES_CANCELED;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
@@ -304,7 +307,12 @@ public class ActivityStarterTests extends WindowTestsBase {
    }
    }


    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags) {
    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags) {
        return prepareStarter(launchFlags, true /* mockGetLaunchStack */);
        return prepareStarter(launchFlags, true /* mockGetLaunchStack */, LAUNCH_MULTIPLE);
    }

    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags,
            boolean mockGetLaunchStack) {
        return prepareStarter(launchFlags, mockGetLaunchStack, LAUNCH_MULTIPLE);
    }
    }


    /**
    /**
@@ -318,7 +326,7 @@ public class ActivityStarterTests extends WindowTestsBase {
     * @return A {@link ActivityStarter} with default setup.
     * @return A {@link ActivityStarter} with default setup.
     */
     */
    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags,
    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags,
            boolean mockGetLaunchStack) {
            boolean mockGetLaunchStack, int launchMode) {
        // always allow test to start activity.
        // always allow test to start activity.
        doReturn(true).when(mSupervisor).checkStartAnyActivityPermission(
        doReturn(true).when(mSupervisor).checkStartAnyActivityPermission(
                any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), any(),
                any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), any(),
@@ -362,6 +370,7 @@ public class ActivityStarterTests extends WindowTestsBase {


        info.applicationInfo = new ApplicationInfo();
        info.applicationInfo = new ApplicationInfo();
        info.applicationInfo.packageName = ActivityBuilder.getDefaultComponent().getPackageName();
        info.applicationInfo.packageName = ActivityBuilder.getDefaultComponent().getPackageName();
        info.launchMode = launchMode;


        return new ActivityStarter(mController, mAtm,
        return new ActivityStarter(mController, mAtm,
                mAtm.mStackSupervisor, mock(ActivityStartInterceptor.class))
                mAtm.mStackSupervisor, mock(ActivityStartInterceptor.class))
@@ -416,7 +425,8 @@ public class ActivityStarterTests extends WindowTestsBase {
    @Test
    @Test
    public void testSplitScreenDeliverToTop() {
    public void testSplitScreenDeliverToTop() {
        final ActivityStarter starter = prepareStarter(
        final ActivityStarter starter = prepareStarter(
                FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | FLAG_ACTIVITY_SINGLE_TOP, false);
                FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | FLAG_ACTIVITY_SINGLE_TOP,
                false /* mockGetLaunchStack */);
        final ActivityRecord splitPrimaryFocusActivity =
        final ActivityRecord splitPrimaryFocusActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord splitSecondReusableActivity =
        final ActivityRecord splitSecondReusableActivity =
@@ -584,6 +594,12 @@ public class ActivityStarterTests extends WindowTestsBase {
                UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
                UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
                true, false, false, false, false);
                true, false, false, false, false);
        runAndVerifyBackgroundActivityStartsSubtest(
                "disallowed_pinned_singleinstance_aborted", true,
                UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
                false, false, false, false, false, true);

    }
    }


    /**
    /**
@@ -647,11 +663,28 @@ public class ActivityStarterTests extends WindowTestsBase {
            boolean callerIsTempAllowed,
            boolean callerIsTempAllowed,
            boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges,
            boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges,
            boolean isCallingUidDeviceOwner) {
            boolean isCallingUidDeviceOwner) {
        runAndVerifyBackgroundActivityStartsSubtest(name, shouldHaveAborted, callingUid,
                callingUidHasVisibleWindow, callingUidProcState, realCallingUid,
                realCallingUidHasVisibleWindow, realCallingUidProcState,
                hasForegroundActivities, callerIsRecents, callerIsTempAllowed,
                callerIsInstrumentingWithBackgroundActivityStartPrivileges,
                isCallingUidDeviceOwner, false /* isPinnedSingleInstance */);
    }

    private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
            int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
            int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
            boolean hasForegroundActivities, boolean callerIsRecents,
            boolean callerIsTempAllowed,
            boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges,
            boolean isCallingUidDeviceOwner,
            boolean isPinnedSingleInstance) {
        // window visibility
        // window visibility
        doReturn(callingUidHasVisibleWindow).when(mAtm.mWindowManager.mRoot)
        doReturn(callingUidHasVisibleWindow).when(mAtm.mWindowManager.mRoot)
                .isAnyNonToastWindowVisibleForUid(callingUid);
                .isAnyNonToastWindowVisibleForUid(callingUid);
        doReturn(realCallingUidHasVisibleWindow).when(mAtm.mWindowManager.mRoot)
        doReturn(realCallingUidHasVisibleWindow).when(mAtm.mWindowManager.mRoot)
                .isAnyNonToastWindowVisibleForUid(realCallingUid);
                .isAnyNonToastWindowVisibleForUid(realCallingUid);

        // process importance
        // process importance
        doReturn(callingUidProcState).when(mAtm).getUidState(callingUid);
        doReturn(callingUidProcState).when(mAtm).getUidState(callingUid);
        doReturn(realCallingUidProcState).when(mAtm).getUidState(realCallingUid);
        doReturn(realCallingUidProcState).when(mAtm).getUidState(realCallingUid);
@@ -679,9 +712,20 @@ public class ActivityStarterTests extends WindowTestsBase {
        // callingUid is the device owner
        // callingUid is the device owner
        doReturn(isCallingUidDeviceOwner).when(mAtm).isDeviceOwner(callingUid);
        doReturn(isCallingUidDeviceOwner).when(mAtm).isDeviceOwner(callingUid);


        int launchMode = LAUNCH_MULTIPLE;
        if (isPinnedSingleInstance) {
            final ActivityRecord baseActivity =
                    new ActivityBuilder(mAtm).setCreateTask(true).build();
            baseActivity.getRootTask()
                    .setWindowingMode(WINDOWING_MODE_PINNED);
            doReturn(baseActivity).when(mRootWindowContainer).findTask(any(), any());
            launchMode = LAUNCH_SINGLE_INSTANCE;
        }

        final ActivityOptions options = spy(ActivityOptions.makeBasic());
        final ActivityOptions options = spy(ActivityOptions.makeBasic());
        ActivityRecord[] outActivity = new ActivityRecord[1];
        ActivityRecord[] outActivity = new ActivityRecord[1];
        ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
        ActivityStarter starter = prepareStarter(
                FLAG_ACTIVITY_NEW_TASK, true, launchMode)
                .setCallingPackage("com.whatever.dude")
                .setCallingPackage("com.whatever.dude")
                .setCaller(caller)
                .setCaller(caller)
                .setCallingUid(callingUid)
                .setCallingUid(callingUid)