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

Commit 2d7fb7b2 authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge changes I1d593900,I179c69c1 into tm-qpr-dev

* changes:
  Move home task behind visible task
  Move desktop mode logic out of ShellTaskOrganizer
parents 32e3767e 4383e8e4
Loading
Loading
Loading
Loading
+16 −54
Original line number Original line Diff line number Diff line
@@ -16,14 +16,12 @@


package com.android.wm.shell;
package com.android.wm.shell;


import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;


import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;


@@ -48,7 +46,6 @@ import android.window.StartingWindowInfo;
import android.window.StartingWindowRemovalInfo;
import android.window.StartingWindowRemovalInfo;
import android.window.TaskAppearedInfo;
import android.window.TaskAppearedInfo;
import android.window.TaskOrganizer;
import android.window.TaskOrganizer;
import android.window.WindowContainerTransaction;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.protolog.common.ProtoLog;
@@ -567,6 +564,22 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
        }
        }
    }
    }


    /**
     * Return list of {@link RunningTaskInfo}s for the given display.
     *
     * @return filtered list of tasks or empty list
     */
    public ArrayList<RunningTaskInfo> getRunningTasks(int displayId) {
        ArrayList<RunningTaskInfo> result = new ArrayList<>();
        for (int i = 0; i < mTasks.size(); i++) {
            RunningTaskInfo taskInfo = mTasks.valueAt(i).getTaskInfo();
            if (taskInfo.displayId == displayId) {
                result.add(taskInfo);
            }
        }
        return result;
    }

    /** Gets running task by taskId. Returns {@code null} if no such task observed. */
    /** Gets running task by taskId. Returns {@code null} if no such task observed. */
    @Nullable
    @Nullable
    public RunningTaskInfo getRunningTaskInfo(int taskId) {
    public RunningTaskInfo getRunningTaskInfo(int taskId) {
@@ -693,57 +706,6 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
        taskListener.reparentChildSurfaceToTask(taskId, sc, t);
        taskListener.reparentChildSurfaceToTask(taskId, sc, t);
    }
    }


    /**
     * Create a {@link WindowContainerTransaction} to clear task bounds.
     *
     * Only affects tasks that have {@link RunningTaskInfo#getActivityType()} set to
     * {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
     *
     * @param displayId display id for tasks that will have bounds cleared
     * @return {@link WindowContainerTransaction} with pending operations to clear bounds
     */
    public WindowContainerTransaction prepareClearBoundsForStandardTasks(int displayId) {
        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "prepareClearBoundsForTasks: displayId=%d", displayId);
        WindowContainerTransaction wct = new WindowContainerTransaction();
        for (int i = 0; i < mTasks.size(); i++) {
            RunningTaskInfo taskInfo = mTasks.valueAt(i).getTaskInfo();
            if ((taskInfo.displayId == displayId) && (taskInfo.getActivityType()
                    == WindowConfiguration.ACTIVITY_TYPE_STANDARD)) {
                ProtoLog.d(WM_SHELL_DESKTOP_MODE, "clearing bounds for token=%s taskInfo=%s",
                        taskInfo.token, taskInfo);
                wct.setBounds(taskInfo.token, null);
            }
        }
        return wct;
    }

    /**
     * Create a {@link WindowContainerTransaction} to clear task level freeform setting.
     *
     * Only affects tasks that have {@link RunningTaskInfo#getActivityType()} set to
     * {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
     *
     * @param displayId display id for tasks that will have windowing mode reset to {@link
     *                  WindowConfiguration#WINDOWING_MODE_UNDEFINED}
     * @return {@link WindowContainerTransaction} with pending operations to clear windowing mode
     */
    public WindowContainerTransaction prepareClearFreeformForStandardTasks(int displayId) {
        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "prepareClearFreeformForTasks: displayId=%d", displayId);
        WindowContainerTransaction wct = new WindowContainerTransaction();
        for (int i = 0; i < mTasks.size(); i++) {
            RunningTaskInfo taskInfo = mTasks.valueAt(i).getTaskInfo();
            if (taskInfo.displayId == displayId
                    && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
                    && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
                ProtoLog.d(WM_SHELL_DESKTOP_MODE,
                        "clearing windowing mode for token=%s taskInfo=%s", taskInfo.token,
                        taskInfo);
                wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
            }
        }
        return wct;
    }

    private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info,
    private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info,
            int event) {
            int event) {
        ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo;
        ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo;
+68 −16
Original line number Original line Diff line number Diff line
@@ -16,8 +16,11 @@


package com.android.wm.shell.desktopmode;
package com.android.wm.shell.desktopmode;


import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -151,21 +154,18 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll


        int displayId = mContext.getDisplayId();
        int displayId = mContext.getDisplayId();


        ArrayList<RunningTaskInfo> runningTasks = mShellTaskOrganizer.getRunningTasks(displayId);

        WindowContainerTransaction wct = new WindowContainerTransaction();
        WindowContainerTransaction wct = new WindowContainerTransaction();
        // Reset freeform windowing mode that is set per task level (tasks should inherit
        // Reset freeform windowing mode that is set per task level so tasks inherit it
        // container value)
        clearFreeformForStandardTasks(runningTasks, wct);
        wct.merge(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(displayId),
                true /* transfer */);
        int targetWindowingMode;
        if (active) {
        if (active) {
            targetWindowingMode = WINDOWING_MODE_FREEFORM;
            moveHomeBehindVisibleTasks(runningTasks, wct);
            setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FREEFORM, wct);
        } else {
        } else {
            targetWindowingMode = WINDOWING_MODE_FULLSCREEN;
            clearBoundsForStandardTasks(runningTasks, wct);
            // Clear any resized bounds
            setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FULLSCREEN, wct);
            wct.merge(mShellTaskOrganizer.prepareClearBoundsForStandardTasks(displayId),
                    true /* transfer */);
        }
        }
        prepareWindowingModeChange(wct, displayId, targetWindowingMode);
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            mTransitions.startTransition(TRANSIT_CHANGE, wct, null);
            mTransitions.startTransition(TRANSIT_CHANGE, wct, null);
        } else {
        } else {
@@ -173,17 +173,69 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
        }
        }
    }
    }


    private void prepareWindowingModeChange(WindowContainerTransaction wct,
    private WindowContainerTransaction clearBoundsForStandardTasks(
            int displayId, @WindowConfiguration.WindowingMode int windowingMode) {
            ArrayList<RunningTaskInfo> runningTasks, WindowContainerTransaction wct) {
        DisplayAreaInfo displayAreaInfo = mRootTaskDisplayAreaOrganizer
        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearBoundsForTasks");
                .getDisplayAreaInfo(displayId);
        for (RunningTaskInfo taskInfo : runningTasks) {
            if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
                ProtoLog.v(WM_SHELL_DESKTOP_MODE, "clearing bounds for token=%s taskInfo=%s",
                        taskInfo.token, taskInfo);
                wct.setBounds(taskInfo.token, null);
            }
        }
        return wct;
    }

    private void clearFreeformForStandardTasks(ArrayList<RunningTaskInfo> runningTasks,
            WindowContainerTransaction wct) {
        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearFreeformForTasks");
        for (RunningTaskInfo taskInfo : runningTasks) {
            if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
                    && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
                ProtoLog.v(WM_SHELL_DESKTOP_MODE,
                        "clearing windowing mode for token=%s taskInfo=%s", taskInfo.token,
                        taskInfo);
                wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
            }
        }
    }

    private void moveHomeBehindVisibleTasks(ArrayList<RunningTaskInfo> runningTasks,
            WindowContainerTransaction wct) {
        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks");
        RunningTaskInfo homeTask = null;
        ArrayList<RunningTaskInfo> visibleTasks = new ArrayList<>();
        for (RunningTaskInfo taskInfo : runningTasks) {
            if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
                homeTask = taskInfo;
            } else if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
                    && taskInfo.isVisible()) {
                visibleTasks.add(taskInfo);
            }
        }
        if (homeTask == null) {
            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: home task not found");
        } else {
            ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: visible tasks %d",
                    visibleTasks.size());
            wct.reorder(homeTask.getToken(), true /* onTop */);
            for (RunningTaskInfo task : visibleTasks) {
                wct.reorder(task.getToken(), true /* onTop */);
            }
        }
    }

    private void setDisplayAreaWindowingMode(int displayId,
            @WindowConfiguration.WindowingMode int windowingMode, WindowContainerTransaction wct) {
        DisplayAreaInfo displayAreaInfo = mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(
                displayId);
        if (displayAreaInfo == null) {
        if (displayAreaInfo == null) {
            ProtoLog.e(WM_SHELL_DESKTOP_MODE,
            ProtoLog.e(WM_SHELL_DESKTOP_MODE,
                    "unable to update windowing mode for display %d display not found", displayId);
                    "unable to update windowing mode for display %d display not found", displayId);
            return;
            return;
        }
        }


        ProtoLog.d(WM_SHELL_DESKTOP_MODE,
        ProtoLog.v(WM_SHELL_DESKTOP_MODE,
                "setWindowingMode: displayId=%d current wmMode=%d new wmMode=%d", displayId,
                "setWindowingMode: displayId=%d current wmMode=%d new wmMode=%d", displayId,
                displayAreaInfo.configuration.windowConfiguration.getWindowingMode(),
                displayAreaInfo.configuration.windowConfiguration.getWindowingMode(),
                windowingMode);
                windowingMode);
+0 −130
Original line number Original line Diff line number Diff line
@@ -16,13 +16,9 @@


package com.android.wm.shell;
package com.android.wm.shell;


import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -34,8 +30,6 @@ import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIO


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeFalse;
@@ -44,11 +38,9 @@ import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.TaskInfo;
import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.content.LocusId;
import android.content.LocusId;
import android.content.pm.ParceledListSlice;
import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.Binder;
@@ -61,8 +53,6 @@ import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.ITaskOrganizerController;
import android.window.TaskAppearedInfo;
import android.window.TaskAppearedInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction.Change;


import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
@@ -638,130 +628,10 @@ public class ShellTaskOrganizerTests extends ShellTestCase {
        verify(mTaskOrganizerController).restartTaskTopActivityProcessIfVisible(task1.token);
        verify(mTaskOrganizerController).restartTaskTopActivityProcessIfVisible(task1.token);
    }
    }


    @Test
    public void testPrepareClearBoundsForStandardTasks() {
        MockToken token1 = new MockToken();
        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_UNDEFINED, token1);
        mOrganizer.onTaskAppeared(task1, null);

        MockToken token2 = new MockToken();
        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_UNDEFINED, token2);
        mOrganizer.onTaskAppeared(task2, null);

        MockToken otherDisplayToken = new MockToken();
        RunningTaskInfo otherDisplayTask = createTaskInfo(3, WINDOWING_MODE_UNDEFINED,
                otherDisplayToken);
        otherDisplayTask.displayId = 2;
        mOrganizer.onTaskAppeared(otherDisplayTask, null);

        WindowContainerTransaction wct = mOrganizer.prepareClearBoundsForStandardTasks(1);

        assertEquals(wct.getChanges().size(), 2);
        Change boundsChange1 = wct.getChanges().get(token1.binder());
        assertNotNull(boundsChange1);
        assertNotEquals(
                (boundsChange1.getWindowSetMask() & WindowConfiguration.WINDOW_CONFIG_BOUNDS), 0);
        assertTrue(boundsChange1.getConfiguration().windowConfiguration.getBounds().isEmpty());

        Change boundsChange2 = wct.getChanges().get(token2.binder());
        assertNotNull(boundsChange2);
        assertNotEquals(
                (boundsChange2.getWindowSetMask() & WindowConfiguration.WINDOW_CONFIG_BOUNDS), 0);
        assertTrue(boundsChange2.getConfiguration().windowConfiguration.getBounds().isEmpty());
    }

    @Test
    public void testPrepareClearBoundsForStandardTasks_onlyClearActivityTypeStandard() {
        MockToken token1 = new MockToken();
        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_UNDEFINED, token1);
        mOrganizer.onTaskAppeared(task1, null);

        MockToken token2 = new MockToken();
        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_UNDEFINED, token2);
        task2.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME);
        mOrganizer.onTaskAppeared(task2, null);

        WindowContainerTransaction wct = mOrganizer.prepareClearBoundsForStandardTasks(1);

        // Only clear bounds for task1
        assertEquals(1, wct.getChanges().size());
        assertNotNull(wct.getChanges().get(token1.binder()));
    }

    @Test
    public void testPrepareClearFreeformForStandardTasks() {
        MockToken token1 = new MockToken();
        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_FREEFORM, token1);
        mOrganizer.onTaskAppeared(task1, null);

        MockToken token2 = new MockToken();
        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_MULTI_WINDOW, token2);
        mOrganizer.onTaskAppeared(task2, null);

        MockToken otherDisplayToken = new MockToken();
        RunningTaskInfo otherDisplayTask = createTaskInfo(3, WINDOWING_MODE_FREEFORM,
                otherDisplayToken);
        otherDisplayTask.displayId = 2;
        mOrganizer.onTaskAppeared(otherDisplayTask, null);

        WindowContainerTransaction wct = mOrganizer.prepareClearFreeformForStandardTasks(1);

        // Only task with freeform windowing mode and the right display should be updated
        assertEquals(wct.getChanges().size(), 1);
        Change wmModeChange1 = wct.getChanges().get(token1.binder());
        assertNotNull(wmModeChange1);
        assertEquals(wmModeChange1.getWindowingMode(), WINDOWING_MODE_UNDEFINED);
    }

    @Test
    public void testPrepareClearFreeformForStandardTasks_onlyClearActivityTypeStandard() {
        MockToken token1 = new MockToken();
        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_FREEFORM, token1);
        mOrganizer.onTaskAppeared(task1, null);

        MockToken token2 = new MockToken();
        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_FREEFORM, token2);
        task2.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME);
        mOrganizer.onTaskAppeared(task2, null);

        WindowContainerTransaction wct = mOrganizer.prepareClearFreeformForStandardTasks(1);

        // Only clear freeform for task1
        assertEquals(1, wct.getChanges().size());
        assertNotNull(wct.getChanges().get(token1.binder()));
    }

    private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
    private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
        RunningTaskInfo taskInfo = new RunningTaskInfo();
        RunningTaskInfo taskInfo = new RunningTaskInfo();
        taskInfo.taskId = taskId;
        taskInfo.taskId = taskId;
        taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
        taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
        return taskInfo;
        return taskInfo;
    }
    }

    private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode, MockToken token) {
        RunningTaskInfo taskInfo = createTaskInfo(taskId, windowingMode);
        taskInfo.displayId = 1;
        taskInfo.token = token.token();
        taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
        return taskInfo;
    }

    private static class MockToken {
        private final WindowContainerToken mToken;
        private final IBinder mBinder;

        MockToken() {
            mToken = mock(WindowContainerToken.class);
            mBinder = mock(IBinder.class);
            when(mToken.asBinder()).thenReturn(mBinder);
        }

        WindowContainerToken token() {
            return mToken;
        }

        IBinder binder() {
            return mBinder;
        }
    }
}
}
+174 −103

File changed.

Preview size limit exceeded, changes collapsed.