Merge "Organize Fullscreen tasks"

This commit is contained in:
Evan Rosky
2020-09-11 01:56:00 +00:00
committed by Android (Google) Code Review
12 changed files with 166 additions and 88 deletions

View File

@@ -1,6 +1,12 @@
{ {
"version": "1.0.0", "version": "1.0.0",
"messages": { "messages": {
"-1501874464": {
"message": "Fullscreen Task Appeared: #%d",
"level": "VERBOSE",
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
},
"-1340279385": { "-1340279385": {
"message": "Remove listener=%s", "message": "Remove listener=%s",
"level": "VERBOSE", "level": "VERBOSE",
@@ -31,6 +37,12 @@
"group": "WM_SHELL_TASK_ORG", "group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
}, },
"564235578": {
"message": "Fullscreen Task Vanished: #%d",
"level": "VERBOSE",
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
},
"980952660": { "980952660": {
"message": "Task root back pressed taskId=%d", "message": "Task root back pressed taskId=%d",
"level": "VERBOSE", "level": "VERBOSE",

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell;
import android.app.ActivityManager;
import android.util.ArraySet;
import android.util.Slog;
import android.view.SurfaceControl;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
private static final String TAG = "FullscreenTaskOrg";
private final TransactionPool mTransactionPool;
private final ArraySet<Integer> mTasks = new ArraySet<>();
FullscreenTaskListener(TransactionPool transactionPool) {
mTransactionPool = transactionPool;
}
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
synchronized (mTasks) {
if (mTasks.contains(taskInfo.taskId)) {
throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
}
mTasks.add(taskInfo.taskId);
final SurfaceControl.Transaction t = mTransactionPool.acquire();
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
taskInfo.taskId);
t.show(leash);
t.apply();
}
}
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
synchronized (mTasks) {
if (!mTasks.remove(taskInfo.taskId)) {
Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
return;
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
taskInfo.taskId);
}
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
}
}

View File

@@ -16,6 +16,8 @@
package com.android.wm.shell; package com.android.wm.shell;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.RunningTaskInfo;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
@@ -26,6 +28,7 @@ import android.window.TaskOrganizer;
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;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.ArrayList; import java.util.ArrayList;
@@ -56,13 +59,16 @@ public class ShellTaskOrganizer extends TaskOrganizer {
// require us to report to both old and new listeners) // require us to report to both old and new listeners)
private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>(); private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>();
public ShellTaskOrganizer() { public ShellTaskOrganizer(TransactionPool transactionPool) {
super(); super();
addListener(new FullscreenTaskListener(transactionPool), WINDOWING_MODE_FULLSCREEN);
} }
@VisibleForTesting @VisibleForTesting
ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController) { ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
TransactionPool transactionPool) {
super(taskOrganizerController); super(taskOrganizerController);
addListener(new FullscreenTaskListener(transactionPool), WINDOWING_MODE_FULLSCREEN);
} }
/** /**
@@ -125,6 +131,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId); Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId);
int winMode = getWindowingMode(taskInfo); int winMode = getWindowingMode(taskInfo);
int prevWinMode = getWindowingMode(data.first); int prevWinMode = getWindowingMode(data.first);
mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second));
if (prevWinMode != -1 && prevWinMode != winMode) { if (prevWinMode != -1 && prevWinMode != winMode) {
// TODO: We currently send vanished/appeared as the task moves between win modes, but // TODO: We currently send vanished/appeared as the task moves between win modes, but
// we should consider adding a different mode-changed callback // we should consider adding a different mode-changed callback

View File

@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.RunningTaskInfo;
@@ -32,6 +33,8 @@ import android.window.ITaskOrganizerController;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.TransactionPool;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -51,6 +54,7 @@ public class ShellTaskOrganizerTests {
private ITaskOrganizerController mTaskOrganizerController; private ITaskOrganizerController mTaskOrganizerController;
ShellTaskOrganizer mOrganizer; ShellTaskOrganizer mOrganizer;
private final TransactionPool mTransactionPool = mock(TransactionPool.class);
private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener { private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener {
final ArrayList<RunningTaskInfo> appeared = new ArrayList<>(); final ArrayList<RunningTaskInfo> appeared = new ArrayList<>();
@@ -81,7 +85,7 @@ public class ShellTaskOrganizerTests {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController); mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController, mTransactionPool);
} }
@Test @Test

View File

@@ -45,6 +45,7 @@ import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto; import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.nano.WmShellTraceProto; import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHanded;
@@ -76,6 +77,9 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
private final Optional<Pip> mPipOptional; private final Optional<Pip> mPipOptional;
private final Optional<SplitScreen> mSplitScreenOptional; private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<OneHanded> mOneHandedOptional; private final Optional<OneHanded> mOneHandedOptional;
// Inject the organizer directly in case the optionals aren't loaded to depend on it. There
// are non-optional windowing features like FULLSCREEN.
private final ShellTaskOrganizer mShellTaskOrganizer;
private final ProtoTracer mProtoTracer; private final ProtoTracer mProtoTracer;
@Inject @Inject
@@ -89,6 +93,7 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
Optional<Pip> pipOptional, Optional<Pip> pipOptional,
Optional<SplitScreen> splitScreenOptional, Optional<SplitScreen> splitScreenOptional,
Optional<OneHanded> oneHandedOptional, Optional<OneHanded> oneHandedOptional,
ShellTaskOrganizer shellTaskOrganizer,
ProtoTracer protoTracer) { ProtoTracer protoTracer) {
super(context); super(context);
mCommandQueue = commandQueue; mCommandQueue = commandQueue;
@@ -101,6 +106,7 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
mPipOptional = pipOptional; mPipOptional = pipOptional;
mSplitScreenOptional = splitScreenOptional; mSplitScreenOptional = splitScreenOptional;
mOneHandedOptional = oneHandedOptional; mOneHandedOptional = oneHandedOptional;
mShellTaskOrganizer = shellTaskOrganizer;
mProtoTracer = protoTracer; mProtoTracer = protoTracer;
mProtoTracer.add(this); mProtoTracer.add(this);
} }

View File

@@ -96,8 +96,8 @@ public abstract class WMShellBaseModule {
@SysUISingleton @SysUISingleton
@Provides @Provides
static ShellTaskOrganizer provideShellTaskOrganizer() { static ShellTaskOrganizer provideShellTaskOrganizer(TransactionPool transactionPool) {
ShellTaskOrganizer organizer = new ShellTaskOrganizer(); ShellTaskOrganizer organizer = new ShellTaskOrganizer(transactionPool);
organizer.registerOrganizer(); organizer.registerOrganizer();
return organizer; return organizer;
} }

View File

@@ -35,6 +35,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.tracing.ProtoTracer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedGestureHandler; import com.android.wm.shell.onehanded.OneHandedGestureHandler;
@@ -64,6 +65,7 @@ public class WMShellTest extends SysuiTestCase {
@Mock Pip mPip; @Mock Pip mPip;
@Mock SplitScreen mSplitScreen; @Mock SplitScreen mSplitScreen;
@Mock OneHanded mOneHanded; @Mock OneHanded mOneHanded;
@Mock ShellTaskOrganizer mTaskOrganizer;
@Mock ProtoTracer mProtoTracer; @Mock ProtoTracer mProtoTracer;
@Before @Before
@@ -72,7 +74,7 @@ public class WMShellTest extends SysuiTestCase {
mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor, mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor,
mActivityManagerWrapper, mDisplayImeController, mNavigationModeController, mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen), mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
Optional.of(mOneHanded), mProtoTracer); Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);
} }
@Test @Test

View File

@@ -16,6 +16,7 @@
package com.android.server.wm; package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
@@ -308,10 +309,13 @@ final class InputMonitor {
* This means we need to make sure that these changes in crop are reflected * This means we need to make sure that these changes in crop are reflected
* in the input windows, and so ensure this flag is set so that * in the input windows, and so ensure this flag is set so that
* the input crop always reflects the surface hierarchy. * the input crop always reflects the surface hierarchy.
* we may have some issues with modal-windows, but I guess we can *
* cross that bridge when we come to implementing full-screen TaskOrg * TODO(b/168252846): we have some issues with modal-windows, so we need to
* cross that bridge now that we organize full-screen Tasks.
*/ */
if (child.getTask() != null && child.getTask().isOrganized()) { if (child.getTask() != null
&& child.getTask().isOrganized()
&& child.getTask().getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
inputWindowHandle.replaceTouchableRegionWithCrop(null /* Use this surfaces crop */); inputWindowHandle.replaceTouchableRegionWithCrop(null /* Use this surfaces crop */);
} }

View File

@@ -1393,7 +1393,8 @@ class Task extends WindowContainer<WindowContainer> {
} }
if (display != null) { if (display != null) {
// TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here... // TODO(b/168037178): Chat with the erosky@ of this code to see if this really makes
// sense here...
// Rotations are relative to the display. This means if there are 2 displays rotated // Rotations are relative to the display. This means if there are 2 displays rotated
// differently (eg. 2 monitors with one landscape and one portrait), moving a stack // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
// from one to the other could look like a rotation change. To prevent this // from one to the other could look like a rotation change. To prevent this
@@ -1407,11 +1408,16 @@ class Task extends WindowContainer<WindowContainer> {
super.onParentChanged(newParent, oldParent); super.onParentChanged(newParent, oldParent);
// TODO(NOW): The check for null display content and setting it to null doesn't really // Call this again after super onParentChanged in-case the surface wasn't created yet
// make sense here... // (happens when the task is first inserted into the hierarchy). It's a no-op if it
// already ran fully within super.onParentChanged
updateTaskOrganizerState(false /* forceUpdate */);
// TODO(stack-merge): This is mostly taking care of the case where the stask is removing from // TODO(b/168037178): The check for null display content and setting it to null doesn't
// the display, so we should probably consolidate it there instead. // really make sense here...
// TODO(b/168037178): This is mostly taking care of the case where the stask is removing
// from the display, so we should probably consolidate it there instead.
if (getParent() == null && mDisplayContent != null) { if (getParent() == null && mDisplayContent != null) {
EventLogTags.writeWmStackRemoved(getRootTaskId()); EventLogTags.writeWmStackRemoved(getRootTaskId());
@@ -4849,6 +4855,11 @@ class Task extends WindowContainer<WindowContainer> {
* @return {@code true} if task organizer changed. * @return {@code true} if task organizer changed.
*/ */
boolean updateTaskOrganizerState(boolean forceUpdate) { boolean updateTaskOrganizerState(boolean forceUpdate) {
if (getSurfaceControl() == null) {
// Can't call onTaskAppeared without a surfacecontrol, so defer this until after one
// is created.
return false;
}
if (!isRootTask()) { if (!isRootTask()) {
return setTaskOrganizer(null); return setTaskOrganizer(null);
} }

View File

@@ -18,10 +18,8 @@ package com.android.server.wm;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
@@ -73,11 +71,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
// The set of modes that are currently supports // The set of modes that are currently supports
// TODO: Remove once the task organizer can support all modes // TODO: Remove once the task organizer can support all modes
@VisibleForTesting @VisibleForTesting
static final int[] SUPPORTED_WINDOWING_MODES = { static final int[] UNSUPPORTED_WINDOWING_MODES = {
WINDOWING_MODE_PINNED, WINDOWING_MODE_UNDEFINED,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, WINDOWING_MODE_FREEFORM
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
WINDOWING_MODE_MULTI_WINDOW,
}; };
private final WindowManagerGlobalLock mGlobalLock; private final WindowManagerGlobalLock mGlobalLock;
@@ -311,18 +307,17 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
synchronized (mGlobalLock) { synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d", ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d",
organizer.asBinder(), uid); organizer.asBinder(), uid);
for (int winMode : SUPPORTED_WINDOWING_MODES) { if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) { mTaskOrganizers.add(organizer);
mTaskOrganizers.add(organizer); mTaskOrganizerStates.put(organizer.asBinder(),
mTaskOrganizerStates.put(organizer.asBinder(), new TaskOrganizerState(organizer, uid));
new TaskOrganizerState(organizer, uid));
}
mService.mRootWindowContainer.forAllTasks((task) -> {
if (task.getWindowingMode() == winMode) {
task.updateTaskOrganizerState(true /* forceUpdate */);
}
});
} }
mService.mRootWindowContainer.forAllTasks((task) -> {
if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, task.getWindowingMode())) {
return;
}
task.updateTaskOrganizerState(true /* forceUpdate */);
});
} }
} finally { } finally {
Binder.restoreCallingIdentity(origId); Binder.restoreCallingIdentity(origId);
@@ -360,12 +355,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
} }
private boolean isSupportedWindowingMode(int winMode) { private boolean isSupportedWindowingMode(int winMode) {
for (int i = 0; i < SUPPORTED_WINDOWING_MODES.length; i++) { return !ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, winMode);
if (SUPPORTED_WINDOWING_MODES[i] == winMode) {
return true;
}
}
return false;
} }
void onTaskAppeared(ITaskOrganizer organizer, Task task) { void onTaskAppeared(ITaskOrganizer organizer, Task task) {
@@ -659,21 +649,18 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
public void dump(PrintWriter pw, String prefix) { public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " "; final String innerPrefix = prefix + " ";
pw.print(prefix); pw.println("TaskOrganizerController:"); pw.print(prefix); pw.println("TaskOrganizerController:");
pw.print(innerPrefix); pw.println("Per windowing mode:"); for (final TaskOrganizerState state : mTaskOrganizerStates.values()) {
for (int i = 0; i < SUPPORTED_WINDOWING_MODES.length; i++) { final ArrayList<Task> tasks = state.mOrganizedTasks;
final int windowingMode = SUPPORTED_WINDOWING_MODES[i]; pw.print(innerPrefix + " ");
pw.println(innerPrefix + " " pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
+ WindowConfiguration.windowingModeToString(windowingMode) + ":"); for (int k = 0; k < tasks.size(); k++) {
for (final TaskOrganizerState state : mTaskOrganizerStates.values()) { final Task task = tasks.get(k);
final ArrayList<Task> tasks = state.mOrganizedTasks; final int mode = task.getWindowingMode();
pw.print(innerPrefix + " "); if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, mode)) {
pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":"); continue;
for (int k = 0; k < tasks.size(); k++) {
final Task task = tasks.get(k);
if (windowingMode == task.getWindowingMode()) {
pw.println(innerPrefix + " " + task);
}
} }
pw.println(innerPrefix + " ("
+ WindowConfiguration.windowingModeToString(mode) + ") " + task);
} }
} }

View File

@@ -16,6 +16,7 @@
package com.android.server.wm; package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -2464,8 +2465,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
boolean isVoiceInteraction) { boolean isVoiceInteraction) {
if (isOrganized()) { if (isOrganized()
// Defer to the task organizer to run animations // TODO(b/161711458): Clean-up when moved to shell.
&& getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
return null; return null;
} }

View File

@@ -229,58 +229,32 @@ public class WindowOrganizerTests extends WindowTestsBase {
final Task task3 = createTask(stack3); final Task task3 = createTask(stack3);
final ITaskOrganizer organizer = registerMockOrganizer(); final ITaskOrganizer organizer = registerMockOrganizer();
// First organizer is registered, verify a task appears when changing windowing mode // verify that tasks are appeared on registration
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); verify(organizer, times(3))
verify(organizer, times(1))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
assertTrue(stack.isOrganized()); assertTrue(stack.isOrganized());
// Now we replace the registration and1 verify the new organizer receives tasks // Now we replace the registration and1 verify the new organizer receives tasks
// newly entering the windowing mode.
final ITaskOrganizer organizer2 = registerMockOrganizer(); final ITaskOrganizer organizer2 = registerMockOrganizer();
stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); verify(organizer2, times(3))
// One each for task and task2
verify(organizer2, times(2))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
verify(organizer2, times(0)).onTaskVanished(any()); verify(organizer2, times(0)).onTaskVanished(any());
// One for task // One for task
verify(organizer).onTaskVanished(any()); verify(organizer, times(3)).onTaskVanished(any());
assertTrue(stack2.isOrganized()); assertTrue(stack2.isOrganized());
// Now we unregister the second one, the first one should automatically be reregistered // Now we unregister the second one, the first one should automatically be reregistered
// so we verify that it's now seeing changes. // so we verify that it's now seeing changes.
mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2); mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
verify(organizer, times(3)) verify(organizer, times(6))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
verify(organizer2, times(2)).onTaskVanished(any()); verify(organizer2, times(3)).onTaskVanished(any());
stack3.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
verify(organizer, times(4))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
verify(organizer2, times(2)).onTaskVanished(any());
assertTrue(stack3.isOrganized());
}
@Test
public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
final ITaskOrganizer organizer = registerMockOrganizer();
final Task stack = createStack();
final Task task = createTask(stack);
final Task task2 = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
verify(organizer, times(1))
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
verify(organizer, times(1)).onTaskVanished(any());
} }
@Test @Test
public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException { public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
final Task stack = createStack(); final Task stack = createStack();
final Task task = createTask(stack); final Task task = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
final ITaskOrganizer organizer = registerMockOrganizer(); final ITaskOrganizer organizer = registerMockOrganizer();
verify(organizer, times(1)) verify(organizer, times(1))