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

Commit 5b091750 authored by Lingyu Feng's avatar Lingyu Feng Committed by Android (Google) Code Review
Browse files

Merge "Revert^2 "Prevent activity being launched on a display where canHostTasks()"" into main

parents 6ceb215e bf2c373d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1793,8 +1793,10 @@ public class ActivityOptions extends ComponentOptions {
    /**
     * Sets the id of the display where the activity should be launched.
     * An app can launch activities on public displays or displays where the app already has
     * activities. Otherwise, trying to launch on a private display or providing an invalid display
     * id will result in an exception.
     * activities. Otherwise, trying to launch on a display for which
     * {@link android.app.ActivityManager#isActivityStartAllowedOnDisplay(Context, int, Intent)}
     * returns {@code false} (such as a private display or providing an invalid display id) will
     * result in an exception.
     * <p>
     * Setting launch display id will be ignored on devices that don't have
     * {@link android.content.pm.PackageManager#FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS}.
+8 −0
Original line number Diff line number Diff line
@@ -1281,6 +1281,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            return false;
        }

        if (DesktopExperienceFlags.ENABLE_MIRROR_DISPLAY_NO_ACTIVITY.isTrue()) {
            if (!displayContent.mDisplay.canHostTasks()) {
                Slog.w(TAG, "Launch on display check: activity launch is not allowed on a "
                        + "display that cannot host tasks");
                return false;
            }
        }

        // Check if the caller has enough privileges to embed activities and launch to private
        // displays.
        final int startAnyPerm = mService.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
+27 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -1069,6 +1070,32 @@ public class ActivityStarterTests extends WindowTestsBase {
        verify(secondaryTaskContainer, times(1)).createRootTask(anyInt(), anyInt(), anyBoolean());
    }

    /**
     * This test ensures that activity launch on a secondary display that cannot host tasks is
     * disallowed, and a SecurityException should be thrown.
     */
    @Test
    public void testStartActivityOnDisplayCannotHostTasks() {
        final ActivityStarter starter = prepareStarter(0);

        // Create a display that cannot host tasks.
        final TestDisplayContent secondaryDisplay =
                new TestDisplayContent.Builder(mAtm, 1000, 1500)
                        .setCanHostTasks(false).build();

        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();

        final ActivityOptions options = ActivityOptions.makeBasic()
                .setLaunchDisplayId(secondaryDisplay.mDisplayId);

        assertThrows(SecurityException.class,
                () -> starter.setReason("testStartActivityOnDisplayCannotHostTasks")
                        .setIntent(activity.intent)
                        .setActivityOptions(options.toBundle(), Binder.getCallingPid(),
                                Binder.getCallingUid())
                        .execute());
    }

    @Test
    public void testWasVisibleInRestartAttempt() {
        final ActivityStarter starter = prepareStarter(
+26 −1
Original line number Diff line number Diff line
@@ -334,7 +334,7 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase {
     * Ensures that a trusted display can launch arbitrary activity and an untrusted display can't.
     */
    @Test
    public void testDisplayCanLaunchActivities() {
    public void testDisplayCanLaunchActivities_trustedDisplay() {
        final Display display = mDisplayContent.mDisplay;
        // An empty info without FLAG_ALLOW_EMBEDDED.
        final ActivityInfo activityInfo = new ActivityInfo();
@@ -355,6 +355,31 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase {
        assertThat(allowedOnUntrusted).isFalse();
    }

    /**
     * Ensures that an arbitrary activity can be launched on a display the can host tasks, and
     * cannot be launched on a display that cannot host tasks.
     */
    @EnableFlags(Flags.FLAG_ENABLE_MIRROR_DISPLAY_NO_ACTIVITY)
    @Test
    public void testDisplayCanLaunchActivities_canHostTasksDisplay() {
        final Display display = mDisplayContent.mDisplay;
        // An empty info without FLAG_ALLOW_EMBEDDED.
        final ActivityInfo activityInfo = new ActivityInfo();
        final int callingPid = 12345;
        final int callingUid = 12345;
        spyOn(display);

        doReturn(true).when(display).canHostTasks();
        final boolean allowedOnCanHostTasks = mSupervisor.isCallerAllowedToLaunchOnDisplay(
                callingPid, callingUid, display.getDisplayId(), activityInfo);
        assertThat(allowedOnCanHostTasks).isTrue();

        doReturn(false).when(display).canHostTasks();
        final boolean allowedOnCannotHostTasks = mSupervisor.isCallerAllowedToLaunchOnDisplay(
                callingPid, callingUid, display.getDisplayId(), activityInfo);
        assertThat(allowedOnCannotHostTasks).isFalse();
    }

    /**
     * Verifies that process state will be updated with pending top without activity state change.
     * E.g. switch focus between resumed activities in multi-window mode.
+9 −0
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ class TestDisplayContent extends DisplayContent {
        private SettingsEntry mOverrideSettings;
        @NonNull
        private DeviceStateController mDeviceStateController = mock(DeviceStateController.class);
        private boolean mCanHostTasks = true;

        Builder(ActivityTaskManagerService service, int width, int height) {
            mService = service;
@@ -160,6 +161,10 @@ class TestDisplayContent extends DisplayContent {
            mInfo.ownerUid = ownerUid;
            return this;
        }
        Builder setCanHostTasks(boolean canHostTasks) {
            mCanHostTasks = canHostTasks;
            return this;
        }
        Builder setCutout(int left, int top, int right, int bottom) {
            final int cutoutFillerSize = 80;
            Rect boundLeft = left != 0 ? new Rect(0, 0, left, cutoutFillerSize) : null;
@@ -215,6 +220,10 @@ class TestDisplayContent extends DisplayContent {
            mInfo.displayId = displayId;
            final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
                    mInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
            spyOn(display);
            if (mCanHostTasks) {
                doReturn(true).when(display).canHostTasks();
            }
            final TestDisplayContent newDisplay = createInternal(display);
            // disable the normal system decorations
            final DisplayPolicy displayPolicy = newDisplay.getDisplayPolicy();