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

Commit af0629a5 authored by lumark's avatar lumark
Browse files

DO NOT MERGE Use realCallerId to check launch display for Bubbles

Since sysui is an entity that decides the App can launch Bubbles
thruogh PendingIntent, it would be make sense that using sysui's realCallerId
to check launch display.

But in RootActivityContainer#getLaunchStack will end up to check launch
display with PendingIntent creater's pid (-1) & uid, which won't pass
the check in the first place.

Add realCallerPid / realCallerUid in
RootActivityContainer#getLaunchStack for ActivityStarter to input
realCallerId to fix above scenario.

Fix: 138753287
Test: atest RootActivityContainerTests#testGetLaunchStackWithRealCallerId
Test: manual as below test steps:
    1) Launch any app
    2) Pop-up a Bubbles
    3) In geusture nav mode, swping up app's activity to close and then press
    Bubble icon to launch Bubble's activity quickly.
    4) Expected app's activity should not shown.

Change-Id: Id3447f6a02f007b66932c59f6f9486688b1e8bad
parent 667db1be
Loading
Loading
Loading
Loading
+29 −1
Original line number Diff line number Diff line
@@ -2700,7 +2700,8 @@ class ActivityStarter {
                 || mPreferredDisplayId != DEFAULT_DISPLAY) {
            final boolean onTop = aOptions == null || !aOptions.getAvoidMoveToFront();
            final ActivityStack stack =
                    mRootActivityContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams);
                    mRootActivityContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams,
                            mRequest.realCallingPid, mRequest.realCallingUid);
            return stack;
        }
        // Otherwise handle adjacent launch.
@@ -2818,11 +2819,24 @@ class ActivityStarter {
        return this;
    }

    /**
     * Sets the pid of the caller who originally started the activity.
     *
     * Normally, the pid/uid would be the calling pid from the binder call.
     * However, in case of a {@link PendingIntent}, the pid/uid pair of the caller is considered
     * the original entity that created the pending intent, in contrast to setRealCallingPid/Uid,
     * which represents the entity who invoked pending intent via {@link PendingIntent#send}.
     */
    ActivityStarter setCallingPid(int pid) {
        mRequest.callingPid = pid;
        return this;
    }

    /**
     * Sets the uid of the caller who originally started the activity.
     *
     * @see #setCallingPid
     */
    ActivityStarter setCallingUid(int uid) {
        mRequest.callingUid = uid;
        return this;
@@ -2833,11 +2847,25 @@ class ActivityStarter {
        return this;
    }

    /**
     * Sets the pid of the caller who requested to launch the activity.
     *
     * The pid/uid represents the caller who launches the activity in this request.
     * It will almost same as setCallingPid/Uid except when processing {@link PendingIntent}:
     * the pid/uid will be the caller who called {@link PendingIntent#send()}.
     *
     * @see #setCallingPid
     */
    ActivityStarter setRealCallingPid(int pid) {
        mRequest.realCallingPid = pid;
        return this;
    }

    /**
     * Sets the uid of the caller who requested to launch the activity.
     *
     * @see #setRealCallingPid
     */
    ActivityStarter setRealCallingUid(int uid) {
        mRequest.realCallingUid = uid;
        return this;
+15 −4
Original line number Diff line number Diff line
@@ -1667,7 +1667,8 @@ class RootActivityContainer extends ConfigurationContainer

    <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
            @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) {
        return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */);
        return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */,
                -1 /* no realCallingPid */, -1 /* no realCallingUid */);
    }

    /**
@@ -1676,13 +1677,16 @@ class RootActivityContainer extends ConfigurationContainer
     * @param r The activity we are trying to launch. Can be null.
     * @param options The activity options used to the launch. Can be null.
     * @param candidateTask The possible task the activity might be launched in. Can be null.
     * @params launchParams The resolved launch params to use.
     * @param launchParams The resolved launch params to use.
     * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
     * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
     *
     * @return The stack to use for the launch or INVALID_STACK_ID.
     */
    <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
            @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
            @Nullable LaunchParamsController.LaunchParams launchParams) {
            @Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,
            int realCallingUid) {
        int taskId = INVALID_TASK_ID;
        int displayId = INVALID_DISPLAY;
        //Rect bounds = null;
@@ -1713,7 +1717,14 @@ class RootActivityContainer extends ConfigurationContainer
        if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
            displayId = launchParams.mPreferredDisplayId;
        }
        if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
        final boolean canLaunchOnDisplayFromStartRequest =
                realCallingPid != 0 && realCallingUid > 0 && r != null
                        && mStackSupervisor.canPlaceEntityOnDisplay(displayId, realCallingPid,
                        realCallingUid, r.info);
        // Checking if the activity's launch caller, or the realCallerId of the activity from
        // start request (i.e. PendingIntent caller) is allowed to launch on the display.
        if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
                || canLaunchOnDisplayFromStartRequest)) {
            if (r != null) {
                stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
                        launchParams);
+1 −1
Original line number Diff line number Diff line
@@ -341,7 +341,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
            doReturn(stack).when(mRootActivityContainer)
                    .getLaunchStack(any(), any(), any(), anyBoolean());
            doReturn(stack).when(mRootActivityContainer)
                    .getLaunchStack(any(), any(), any(), anyBoolean(), any());
                    .getLaunchStack(any(), any(), any(), anyBoolean(), any(), anyInt(), anyInt());
        }

        // Set up mock package manager internal and make sure no unmocked methods are called
+17 −4
Original line number Diff line number Diff line
@@ -204,6 +204,8 @@ class ActivityTestsBase {
        private ActivityStack mStack;
        private int mActivityFlags;
        private int mLaunchMode;
        private int mLaunchedFromPid;
        private int mLaunchedFromUid;

        ActivityBuilder(ActivityTaskManagerService service) {
            mService = service;
@@ -254,6 +256,16 @@ class ActivityTestsBase {
            return this;
        }

        ActivityBuilder setLaunchedFromPid(int pid) {
            mLaunchedFromPid = pid;
            return this;
        }

        ActivityBuilder setLaunchedFromUid(int uid) {
            mLaunchedFromUid = uid;
            return this;
        }

        ActivityRecord build() {
            if (mComponent == null) {
                final int id = sCurrentActivityId++;
@@ -281,10 +293,11 @@ class ActivityTestsBase {
            aInfo.launchMode = mLaunchMode;

            final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
                    0 /* launchedFromPid */, 0, null, intent, null,
                    aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
                    0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
                    mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
                    mLaunchedFromPid /* launchedFromPid */, mLaunchedFromUid /* launchedFromUid */,
                    null, intent, null, aInfo /*aInfo*/, new Configuration(), null /* resultTo */,
                    null /* resultWho */, 0 /* reqCode */, false /*componentSpecified*/,
                    false /* rootVoiceInteraction */, mService.mStackSupervisor,
                    null /* options */, null /* sourceRecord */);
            spyOn(activity);
            activity.mAppWindowToken = mock(AppWindowToken.class);
            doCallRealMethod().when(activity.mAppWindowToken).getOrientationIgnoreVisibility();
+37 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -61,6 +62,7 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
import android.view.DisplayInfo;

import androidx.test.filters.MediumTest;

@@ -816,6 +818,41 @@ public class RootActivityContainerTests extends ActivityTestsBase {
        assertEquals(infoFake1.activityInfo.name, resolvedInfo.first.name);
    }

    /**
     * Test that {@link RootActivityContainer#getLaunchStack} with the real caller id will get the
     * expected stack when requesting the activity launch on the secondary display.
     */
    @Test
    public void testGetLaunchStackWithRealCallerId() {
        // Create a non-system owned virtual display.
        final DisplayInfo info = new DisplayInfo();
        mSupervisor.mService.mContext.getDisplay().getDisplayInfo(info);
        info.type = TYPE_VIRTUAL;
        info.ownerUid = 100;
        final TestActivityDisplay secondaryDisplay = createNewActivityDisplay(info);
        mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);

        // Create an activity with specify the original launch pid / uid.
        final ActivityRecord r = new ActivityBuilder(mService).setLaunchedFromPid(200)
                .setLaunchedFromUid(200).build();

        // Simulate ActivityStarter to find a launch stack for requesting the activity to launch
        // on the secondary display with realCallerId.
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchDisplayId(secondaryDisplay.mDisplayId);
        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
        doReturn(true).when(mSupervisor).canPlaceEntityOnDisplay(secondaryDisplay.mDisplayId,
                300 /* test realCallerPid */, 300 /* test realCallerUid */, r.info);
        final ActivityStack result = mRootActivityContainer.getLaunchStack(r, options,
                null /* task */, true /* onTop */, null, 300 /* test realCallerPid */,
                300 /* test realCallerUid */);

        // Assert that the stack is returned as expected.
        assertNotNull(result);
        assertEquals("The display ID of the stack should same as secondary display ",
                secondaryDisplay.mDisplayId, result.mDisplayId);
    }

    /**
     * Mock {@link RootActivityContainerTests#resolveHomeActivity} for returning consistent activity
     * info for test cases (the original implementation will resolve from the real package manager).