Merge changes I1d593900,I179c69c1 into tm-qpr-dev
* changes: Move home task behind visible task Move desktop mode logic out of ShellTaskOrganizer
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
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.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
|
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
|
||||||
|
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;
|
||||||
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
|
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
|
||||||
@@ -30,13 +33,14 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
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 static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -68,6 +72,9 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
public class DesktopModeControllerTest extends ShellTestCase {
|
public class DesktopModeControllerTest extends ShellTestCase {
|
||||||
@@ -83,9 +90,7 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private Handler mMockHandler;
|
private Handler mMockHandler;
|
||||||
@Mock
|
@Mock
|
||||||
private Transitions mMockTransitions;
|
private Transitions mTransitions;
|
||||||
private TestShellExecutor mExecutor;
|
|
||||||
|
|
||||||
private DesktopModeController mController;
|
private DesktopModeController mController;
|
||||||
private DesktopModeTaskRepository mDesktopModeTaskRepository;
|
private DesktopModeTaskRepository mDesktopModeTaskRepository;
|
||||||
private ShellInit mShellInit;
|
private ShellInit mShellInit;
|
||||||
@@ -97,20 +102,19 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
when(DesktopModeStatus.isActive(any())).thenReturn(true);
|
when(DesktopModeStatus.isActive(any())).thenReturn(true);
|
||||||
|
|
||||||
mShellInit = Mockito.spy(new ShellInit(mTestExecutor));
|
mShellInit = Mockito.spy(new ShellInit(mTestExecutor));
|
||||||
mExecutor = new TestShellExecutor();
|
|
||||||
|
|
||||||
mDesktopModeTaskRepository = new DesktopModeTaskRepository();
|
mDesktopModeTaskRepository = new DesktopModeTaskRepository();
|
||||||
|
|
||||||
mController = new DesktopModeController(mContext, mShellInit, mShellController,
|
mController = new DesktopModeController(mContext, mShellInit, mShellController,
|
||||||
mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mMockTransitions,
|
mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mTransitions,
|
||||||
mDesktopModeTaskRepository, mMockHandler, mExecutor);
|
mDesktopModeTaskRepository, mMockHandler, new TestShellExecutor());
|
||||||
|
|
||||||
when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(anyInt())).thenReturn(
|
when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>());
|
||||||
new WindowContainerTransaction());
|
|
||||||
|
|
||||||
mShellInit.init();
|
mShellInit.init();
|
||||||
clearInvocations(mShellTaskOrganizer);
|
clearInvocations(mShellTaskOrganizer);
|
||||||
clearInvocations(mRootTaskDisplayAreaOrganizer);
|
clearInvocations(mRootTaskDisplayAreaOrganizer);
|
||||||
|
clearInvocations(mTransitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -124,113 +128,133 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDesktopModeEnabled_taskWmClearedDisplaySetToFreeform() {
|
public void testDesktopModeEnabled_rootTdaSetToFreeform() {
|
||||||
// Create a fake WCT to simulate setting task windowing mode to undefined
|
DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
|
||||||
WindowContainerTransaction taskWct = new WindowContainerTransaction();
|
|
||||||
MockToken taskMockToken = new MockToken();
|
|
||||||
taskWct.setWindowingMode(taskMockToken.token(), WINDOWING_MODE_UNDEFINED);
|
|
||||||
when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(
|
|
||||||
mContext.getDisplayId())).thenReturn(taskWct);
|
|
||||||
|
|
||||||
// Create a fake DisplayAreaInfo to check if windowing mode change is set correctly
|
|
||||||
MockToken displayMockToken = new MockToken();
|
|
||||||
DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(displayMockToken.mToken,
|
|
||||||
mContext.getDisplayId(), 0);
|
|
||||||
when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
|
|
||||||
.thenReturn(displayAreaInfo);
|
|
||||||
|
|
||||||
// The test
|
|
||||||
mController.updateDesktopModeActive(true);
|
mController.updateDesktopModeActive(true);
|
||||||
|
WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
|
||||||
|
|
||||||
ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
|
// 1 change: Root TDA windowing mode
|
||||||
WindowContainerTransaction.class);
|
assertThat(wct.getChanges().size()).isEqualTo(1);
|
||||||
verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
|
// Verify WCT has a change for setting windowing mode to freeform
|
||||||
|
Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
|
||||||
// WCT should have 2 changes - clear task wm mode and set display wm mode
|
assertThat(change).isNotNull();
|
||||||
WindowContainerTransaction wct = arg.getValue();
|
assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FREEFORM);
|
||||||
assertThat(wct.getChanges()).hasSize(2);
|
|
||||||
|
|
||||||
// Verify executed WCT has a change for setting task windowing mode to undefined
|
|
||||||
Change taskWmModeChange = wct.getChanges().get(taskMockToken.binder());
|
|
||||||
assertThat(taskWmModeChange).isNotNull();
|
|
||||||
assertThat(taskWmModeChange.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
|
|
||||||
|
|
||||||
// Verify executed WCT has a change for setting display windowing mode to freeform
|
|
||||||
Change displayWmModeChange = wct.getChanges().get(displayAreaInfo.token.asBinder());
|
|
||||||
assertThat(displayWmModeChange).isNotNull();
|
|
||||||
assertThat(displayWmModeChange.getWindowingMode()).isEqualTo(WINDOWING_MODE_FREEFORM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDesktopModeDisabled_taskWmAndBoundsClearedDisplaySetToFullscreen() {
|
public void testDesktopModeDisabled_rootTdaSetToFullscreen() {
|
||||||
// Create a fake WCT to simulate setting task windowing mode to undefined
|
DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
|
||||||
WindowContainerTransaction taskWmWct = new WindowContainerTransaction();
|
|
||||||
MockToken taskWmMockToken = new MockToken();
|
|
||||||
taskWmWct.setWindowingMode(taskWmMockToken.token(), WINDOWING_MODE_UNDEFINED);
|
|
||||||
when(mShellTaskOrganizer.prepareClearFreeformForStandardTasks(
|
|
||||||
mContext.getDisplayId())).thenReturn(taskWmWct);
|
|
||||||
|
|
||||||
// Create a fake WCT to simulate clearing task bounds
|
|
||||||
WindowContainerTransaction taskBoundsWct = new WindowContainerTransaction();
|
|
||||||
MockToken taskBoundsMockToken = new MockToken();
|
|
||||||
taskBoundsWct.setBounds(taskBoundsMockToken.token(), null);
|
|
||||||
when(mShellTaskOrganizer.prepareClearBoundsForStandardTasks(
|
|
||||||
mContext.getDisplayId())).thenReturn(taskBoundsWct);
|
|
||||||
|
|
||||||
// Create a fake DisplayAreaInfo to check if windowing mode change is set correctly
|
|
||||||
MockToken displayMockToken = new MockToken();
|
|
||||||
DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(displayMockToken.mToken,
|
|
||||||
mContext.getDisplayId(), 0);
|
|
||||||
when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
|
|
||||||
.thenReturn(displayAreaInfo);
|
|
||||||
|
|
||||||
// The test
|
|
||||||
mController.updateDesktopModeActive(false);
|
mController.updateDesktopModeActive(false);
|
||||||
|
WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
|
||||||
|
|
||||||
ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
|
// 1 change: Root TDA windowing mode
|
||||||
WindowContainerTransaction.class);
|
assertThat(wct.getChanges().size()).isEqualTo(1);
|
||||||
verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
|
// Verify WCT has a change for setting windowing mode to fullscreen
|
||||||
|
Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
|
||||||
|
assertThat(change).isNotNull();
|
||||||
|
assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
|
||||||
|
}
|
||||||
|
|
||||||
// WCT should have 3 changes - clear task wm mode and bounds and set display wm mode
|
@Test
|
||||||
WindowContainerTransaction wct = arg.getValue();
|
public void testDesktopModeEnabled_windowingModeCleared() {
|
||||||
assertThat(wct.getChanges()).hasSize(3);
|
createMockDisplayArea();
|
||||||
|
RunningTaskInfo freeformTask = createFreeformTask();
|
||||||
|
RunningTaskInfo fullscreenTask = createFullscreenTask();
|
||||||
|
RunningTaskInfo homeTask = createHomeTask();
|
||||||
|
when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
|
||||||
|
Arrays.asList(freeformTask, fullscreenTask, homeTask)));
|
||||||
|
|
||||||
// Verify executed WCT has a change for setting task windowing mode to undefined
|
mController.updateDesktopModeActive(true);
|
||||||
Change taskWmMode = wct.getChanges().get(taskWmMockToken.binder());
|
WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
|
||||||
assertThat(taskWmMode).isNotNull();
|
|
||||||
assertThat(taskWmMode.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
|
|
||||||
|
|
||||||
// Verify executed WCT has a change for clearing task bounds
|
// 2 changes: Root TDA windowing mode and 1 task
|
||||||
Change bounds = wct.getChanges().get(taskBoundsMockToken.binder());
|
assertThat(wct.getChanges().size()).isEqualTo(2);
|
||||||
assertThat(bounds).isNotNull();
|
// No changes for tasks that are not standard or freeform
|
||||||
assertThat(bounds.getWindowSetMask() & WINDOW_CONFIG_BOUNDS).isNotEqualTo(0);
|
assertThat(wct.getChanges().get(fullscreenTask.token.asBinder())).isNull();
|
||||||
assertThat(bounds.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
|
assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
|
||||||
|
// Standard freeform task has windowing mode cleared
|
||||||
|
Change change = wct.getChanges().get(freeformTask.token.asBinder());
|
||||||
|
assertThat(change).isNotNull();
|
||||||
|
assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
// Verify executed WCT has a change for setting display windowing mode to fullscreen
|
@Test
|
||||||
Change displayWmModeChange = wct.getChanges().get(displayAreaInfo.token.asBinder());
|
public void testDesktopModeDisabled_windowingModeAndBoundsCleared() {
|
||||||
assertThat(displayWmModeChange).isNotNull();
|
createMockDisplayArea();
|
||||||
assertThat(displayWmModeChange.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
|
RunningTaskInfo freeformTask = createFreeformTask();
|
||||||
|
RunningTaskInfo fullscreenTask = createFullscreenTask();
|
||||||
|
RunningTaskInfo homeTask = createHomeTask();
|
||||||
|
when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
|
||||||
|
Arrays.asList(freeformTask, fullscreenTask, homeTask)));
|
||||||
|
|
||||||
|
mController.updateDesktopModeActive(false);
|
||||||
|
WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
|
||||||
|
|
||||||
|
// 3 changes: Root TDA windowing mode and 2 tasks
|
||||||
|
assertThat(wct.getChanges().size()).isEqualTo(3);
|
||||||
|
// No changes to home task
|
||||||
|
assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
|
||||||
|
// Standard tasks have bounds cleared
|
||||||
|
assertThatBoundsCleared(wct.getChanges().get(freeformTask.token.asBinder()));
|
||||||
|
assertThatBoundsCleared(wct.getChanges().get(fullscreenTask.token.asBinder()));
|
||||||
|
// Freeform standard tasks have windowing mode cleared
|
||||||
|
assertThat(wct.getChanges().get(
|
||||||
|
freeformTask.token.asBinder()).getWindowingMode()).isEqualTo(
|
||||||
|
WINDOWING_MODE_UNDEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDesktopModeEnabled_homeTaskBehindVisibleTask() {
|
||||||
|
createMockDisplayArea();
|
||||||
|
RunningTaskInfo fullscreenTask1 = createFullscreenTask();
|
||||||
|
fullscreenTask1.isVisible = true;
|
||||||
|
RunningTaskInfo fullscreenTask2 = createFullscreenTask();
|
||||||
|
fullscreenTask2.isVisible = false;
|
||||||
|
RunningTaskInfo homeTask = createHomeTask();
|
||||||
|
when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
|
||||||
|
Arrays.asList(fullscreenTask1, fullscreenTask2, homeTask)));
|
||||||
|
|
||||||
|
mController.updateDesktopModeActive(true);
|
||||||
|
WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
|
||||||
|
|
||||||
|
// Check that there are hierarchy changes for home task and visible task
|
||||||
|
assertThat(wct.getHierarchyOps()).hasSize(2);
|
||||||
|
// First show home task
|
||||||
|
WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||||
|
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||||
|
assertThat(op1.getContainer()).isEqualTo(homeTask.token.asBinder());
|
||||||
|
|
||||||
|
// Then visible task on top of it
|
||||||
|
WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||||
|
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||||
|
assertThat(op2.getContainer()).isEqualTo(fullscreenTask1.token.asBinder());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShowDesktopApps() {
|
public void testShowDesktopApps() {
|
||||||
// Set up two active tasks on desktop
|
// Set up two active tasks on desktop
|
||||||
mDesktopModeTaskRepository.addActiveTask(1);
|
RunningTaskInfo freeformTask1 = createFreeformTask();
|
||||||
mDesktopModeTaskRepository.addActiveTask(2);
|
freeformTask1.lastActiveTime = 100;
|
||||||
MockToken token1 = new MockToken();
|
RunningTaskInfo freeformTask2 = createFreeformTask();
|
||||||
MockToken token2 = new MockToken();
|
freeformTask2.lastActiveTime = 200;
|
||||||
ActivityManager.RunningTaskInfo taskInfo1 = new TestRunningTaskInfoBuilder().setToken(
|
mDesktopModeTaskRepository.addActiveTask(freeformTask1.taskId);
|
||||||
token1.token()).setLastActiveTime(100).build();
|
mDesktopModeTaskRepository.addActiveTask(freeformTask2.taskId);
|
||||||
ActivityManager.RunningTaskInfo taskInfo2 = new TestRunningTaskInfoBuilder().setToken(
|
when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask1.taskId)).thenReturn(
|
||||||
token2.token()).setLastActiveTime(200).build();
|
freeformTask1);
|
||||||
when(mShellTaskOrganizer.getRunningTaskInfo(1)).thenReturn(taskInfo1);
|
when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask2.taskId)).thenReturn(
|
||||||
when(mShellTaskOrganizer.getRunningTaskInfo(2)).thenReturn(taskInfo2);
|
freeformTask2);
|
||||||
|
|
||||||
// Run show desktop apps logic
|
// Run show desktop apps logic
|
||||||
mController.showDesktopApps();
|
mController.showDesktopApps();
|
||||||
ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(
|
ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(
|
||||||
WindowContainerTransaction.class);
|
WindowContainerTransaction.class);
|
||||||
verify(mShellTaskOrganizer).applyTransaction(wctCaptor.capture());
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
|
verify(mTransitions).startTransition(eq(TRANSIT_TO_FRONT), wctCaptor.capture(), any());
|
||||||
|
} else {
|
||||||
|
verify(mShellTaskOrganizer).applyTransaction(wctCaptor.capture());
|
||||||
|
}
|
||||||
WindowContainerTransaction wct = wctCaptor.getValue();
|
WindowContainerTransaction wct = wctCaptor.getValue();
|
||||||
|
|
||||||
// Check wct has reorder calls
|
// Check wct has reorder calls
|
||||||
@@ -239,12 +263,12 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
// Task 2 has activity later, must be first
|
// Task 2 has activity later, must be first
|
||||||
WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||||
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||||
assertThat(op1.getContainer()).isEqualTo(token2.binder());
|
assertThat(op1.getContainer()).isEqualTo(freeformTask2.token.asBinder());
|
||||||
|
|
||||||
// Task 1 should be second
|
// Task 1 should be second
|
||||||
WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(0);
|
WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||||
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||||
assertThat(op2.getContainer()).isEqualTo(token2.binder());
|
assertThat(op2.getContainer()).isEqualTo(freeformTask1.token.asBinder());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -266,7 +290,7 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandleTransitionRequest_notFreeform_returnsNull() {
|
public void testHandleTransitionRequest_notFreeform_returnsNull() {
|
||||||
ActivityManager.RunningTaskInfo trigger = new ActivityManager.RunningTaskInfo();
|
RunningTaskInfo trigger = new RunningTaskInfo();
|
||||||
trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
|
trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
|
||||||
WindowContainerTransaction wct = mController.handleRequest(
|
WindowContainerTransaction wct = mController.handleRequest(
|
||||||
new Binder(),
|
new Binder(),
|
||||||
@@ -276,7 +300,7 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandleTransitionRequest_returnsWct() {
|
public void testHandleTransitionRequest_returnsWct() {
|
||||||
ActivityManager.RunningTaskInfo trigger = new ActivityManager.RunningTaskInfo();
|
RunningTaskInfo trigger = new RunningTaskInfo();
|
||||||
trigger.token = new MockToken().mToken;
|
trigger.token = new MockToken().mToken;
|
||||||
trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
|
trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
|
||||||
WindowContainerTransaction wct = mController.handleRequest(
|
WindowContainerTransaction wct = mController.handleRequest(
|
||||||
@@ -285,6 +309,57 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
assertThat(wct).isNotNull();
|
assertThat(wct).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DisplayAreaInfo createMockDisplayArea() {
|
||||||
|
DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(new MockToken().mToken,
|
||||||
|
mContext.getDisplayId(), 0);
|
||||||
|
when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
|
||||||
|
.thenReturn(displayAreaInfo);
|
||||||
|
return displayAreaInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningTaskInfo createFreeformTask() {
|
||||||
|
return new TestRunningTaskInfoBuilder()
|
||||||
|
.setToken(new MockToken().token())
|
||||||
|
.setActivityType(ACTIVITY_TYPE_STANDARD)
|
||||||
|
.setWindowingMode(WINDOWING_MODE_FREEFORM)
|
||||||
|
.setLastActiveTime(100)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningTaskInfo createFullscreenTask() {
|
||||||
|
return new TestRunningTaskInfoBuilder()
|
||||||
|
.setToken(new MockToken().token())
|
||||||
|
.setActivityType(ACTIVITY_TYPE_STANDARD)
|
||||||
|
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
|
||||||
|
.setLastActiveTime(100)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RunningTaskInfo createHomeTask() {
|
||||||
|
return new TestRunningTaskInfoBuilder()
|
||||||
|
.setToken(new MockToken().token())
|
||||||
|
.setActivityType(ACTIVITY_TYPE_HOME)
|
||||||
|
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
|
||||||
|
.setLastActiveTime(100)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private WindowContainerTransaction getDesktopModeSwitchTransaction() {
|
||||||
|
ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
|
||||||
|
WindowContainerTransaction.class);
|
||||||
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
|
verify(mTransitions).startTransition(eq(TRANSIT_CHANGE), arg.capture(), any());
|
||||||
|
} else {
|
||||||
|
verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
|
||||||
|
}
|
||||||
|
return arg.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatBoundsCleared(Change change) {
|
||||||
|
assertThat((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) != 0).isTrue();
|
||||||
|
assertThat(change.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private static class MockToken {
|
private static class MockToken {
|
||||||
private final WindowContainerToken mToken;
|
private final WindowContainerToken mToken;
|
||||||
private final IBinder mBinder;
|
private final IBinder mBinder;
|
||||||
@@ -298,9 +373,5 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
|||||||
WindowContainerToken token() {
|
WindowContainerToken token() {
|
||||||
return mToken;
|
return mToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
IBinder binder() {
|
|
||||||
return mBinder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user