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

Commit ac01bf68 authored by Kazuki Takise's avatar Kazuki Takise
Browse files

Disallow presentation on unfocused host task

Previoulsy, we only checked the globally focused task if it could
be the host task of a presentation. However, some apps try to
launch a presentation even when it's not focused (as long as they
are resumed they assume that they are on top).

Instead, with this change, the top "visible" task from the same
app is considered to be the host task.

Flag: com.android.window.flags.enable_presentation_disallowed_on_unfocused_host_task
Bug: 435586251
Test: PresentationControllerTests#testPresentationCannotCoverUnfocusedHostTask
Change-Id: Id6bcbf2a31104317522c3790bf196c50bccd982a
parent f85a9d4b
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.window.DesktopExperienceFlags.ENABLE_PRESENTATION_DISALLOWED_ON_UNFOCUSED_HOST_TASK;
import static android.window.DesktopExperienceFlags.ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS;

import static com.android.internal.protolog.WmProtoLogGroups.WM_ERROR;
@@ -149,6 +150,21 @@ class PresentationController implements DisplayManager.DisplayListener {
            if (globallyFocusedTask != null && uid == globallyFocusedTask.effectiveUid) {
                hostTask = globallyFocusedTask;
            }

            if (ENABLE_PRESENTATION_DISALLOWED_ON_UNFOCUSED_HOST_TASK.isTrue()
                    && hostTask == null) {
                final Task[] topVisibleTaskWithSameUid = new Task[1];
                // Assume that the top visible task from the same app is the host task.
                displayContent.mWmService.mRoot.forAllLeafTasks(task -> {
                    if (task.effectiveUid == uid && task.isVisibleRequested()
                            && task.isFocusableAndVisible()) {
                        topVisibleTaskWithSameUid[0] = task;
                        return true;
                    }
                    return false;
                });
                hostTask = topVisibleTaskWithSameUid[0];
            }
        }
        if (hostTask != null && displayId == hostTask.getDisplayId()) {
            // A presentation can't cover its own host task.
+33 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.wm;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRESENTATION;
import static android.view.Display.FLAG_PRIVATE;
@@ -28,6 +30,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.window.flags.Flags.FLAG_ENABLE_PRESENTATION_DISALLOWED_ON_UNFOCUSED_HOST_TASK;
import static com.android.window.flags.Flags.FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS;

import static org.junit.Assert.assertEquals;
@@ -127,7 +130,7 @@ public class PresentationControllerTests extends WindowTestsBase {

    @EnableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
    @Test
    public void testPresentationCannotCoverHostTask() {
    public void testPresentationCannotCoverFocusedHostTask() {
        int uid = Binder.getCallingUid();
        final DisplayContent presentationDisplay = createPresentationDisplay();
        final Task task = createTask(presentationDisplay);
@@ -153,6 +156,35 @@ public class PresentationControllerTests extends WindowTestsBase {
        assertFalse(window.isVisible());
    }

    @EnableFlags({FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS,
            FLAG_ENABLE_PRESENTATION_DISALLOWED_ON_UNFOCUSED_HOST_TASK})
    @Test
    public void testPresentationCannotCoverUnfocusedHostTask() {
        int uid = Binder.getCallingUid();
        final DisplayContent presentationDisplay = createPresentationDisplay();
        final Task hostTask = createTask(presentationDisplay);
        hostTask.effectiveUid = uid;
        final ActivityRecord hostActivity = createActivityRecord(hostTask);
        assertTrue(hostActivity.isVisible());

        // Adding a presentation window over its host task must fail.
        assertAddPresentationWindowFails(uid, presentationDisplay.mDisplayId);

        // Create another task, which makes the host task unfocused.
        final Task taskFromAnotherApp = createTask(presentationDisplay.getDefaultTaskDisplayArea(),
                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
        taskFromAnotherApp.effectiveUid = uid + 1;
        final ActivityRecord activityFromAnotherApp = createActivityRecord(taskFromAnotherApp);
        assertTrue(hostActivity.isVisible());
        assertTrue(activityFromAnotherApp.isVisible());
        assertFalse(hostActivity.isFocusedActivityOnDisplay());
        assertTrue(activityFromAnotherApp.isFocusedActivityOnDisplay());

        // Adding a presentation window over its host task must fail even if the host task is not
        // focused.
        assertAddPresentationWindowFails(uid, presentationDisplay.mDisplayId);
    }

    @EnableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
    @Test
    public void testPresentationCannotLaunchOnAllDisplays() {