diff options
20 files changed, 431 insertions, 196 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index ec7431ca8d3a..a97a9e88a368 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5577,7 +5577,7 @@ package android.window { method @BinderThread public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl); method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo); method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo); - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer(int); + method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer(); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer(); diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl index 1c03b2fdf906..92fa80e40caf 100644 --- a/core/java/android/window/ITaskOrganizerController.aidl +++ b/core/java/android/window/ITaskOrganizerController.aidl @@ -25,11 +25,9 @@ import android.window.WindowContainerTransaction; interface ITaskOrganizerController { /** - * Register a TaskOrganizer to manage tasks as they enter the given windowing mode. - * If there was already a TaskOrganizer for this windowing mode it will be evicted - * and receive taskVanished callbacks in the process. + * Register a TaskOrganizer to manage all the tasks with supported windowing modes. */ - void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode); + void registerTaskOrganizer(ITaskOrganizer organizer); /** * Unregisters a previously registered task organizer. diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index 502680de9bcf..7ec4f99ce959 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -36,14 +36,12 @@ import java.util.List; public class TaskOrganizer extends WindowOrganizer { /** - * Register a TaskOrganizer to manage tasks as they enter the given windowing mode. - * If there was already a TaskOrganizer for this windowing mode it will be evicted - * and receive taskVanished callbacks in the process. + * Register a TaskOrganizer to manage tasks as they enter a supported windowing mode. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public final void registerOrganizer(int windowingMode) { + public final void registerOrganizer() { try { - getController().registerTaskOrganizer(mInterface, windowingMode); + getController().registerTaskOrganizer(mInterface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java index 1b87521f3a96..46c72f88e14b 100644 --- a/core/java/android/window/TaskOrganizerTaskEmbedder.java +++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java @@ -73,7 +73,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { // TODO(wm-shell): This currently prevents other organizers from controlling MULT_WINDOW // windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that // infrastructure is ready. - mTaskOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW); + // mTaskOrganizer.registerOrganizer(); mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true); return super.onInitialize(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java new file mode 100644 index 000000000000..126374829a18 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -0,0 +1,161 @@ +/* + * 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.RunningTaskInfo; +import android.util.Log; +import android.util.Pair; +import android.util.SparseArray; +import android.util.SparseIntArray; +import android.view.Surface; +import android.view.SurfaceControl; +import android.window.TaskOrganizer; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Unified task organizer for all components in the shell. + */ +public class ShellTaskOrganizer extends TaskOrganizer { + + private static final String TAG = "ShellTaskOrganizer"; + + /** + * Callbacks for when the tasks change in the system. + */ + public interface TaskListener { + default void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {} + default void onTaskInfoChanged(RunningTaskInfo taskInfo) {} + default void onTaskVanished(RunningTaskInfo taskInfo) {} + default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {} + } + + private final SparseArray<ArrayList<TaskListener>> mListenersByWindowingMode = + new SparseArray<>(); + + // Keeps track of all the tasks reported to this organizer (changes in windowing mode will + // require us to report to both old and new listeners) + private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>(); + + /** + * Adds a listener for tasks in a specific windowing mode. + */ + public void addListener(TaskListener listener, int... windowingModes) { + for (int winMode : windowingModes) { + ArrayList<TaskListener> listeners = mListenersByWindowingMode.get(winMode); + if (listeners == null) { + listeners = new ArrayList<>(); + mListenersByWindowingMode.put(winMode, listeners); + } + if (listeners.contains(listener)) { + Log.w(TAG, "Listener already exists"); + return; + } + listeners.add(listener); + + // Notify the listener of all existing tasks in that windowing mode + for (int i = mTasks.size() - 1; i >= 0; i--) { + Pair<RunningTaskInfo, SurfaceControl> data = mTasks.valueAt(i); + int taskWinMode = data.first.configuration.windowConfiguration.getWindowingMode(); + if (taskWinMode == winMode) { + listener.onTaskAppeared(data.first, data.second); + } + } + } + } + + /** + * Removes a registered listener. + */ + public void removeListener(TaskListener listener) { + for (int i = 0; i < mListenersByWindowingMode.size(); i++) { + mListenersByWindowingMode.valueAt(i).remove(listener); + } + } + + @Override + public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { + mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, leash)); + ArrayList<TaskListener> listeners = mListenersByWindowingMode.get( + getWindowingMode(taskInfo)); + if (listeners != null) { + for (int i = listeners.size() - 1; i >= 0; i--) { + listeners.get(i).onTaskAppeared(taskInfo, leash); + } + } + } + + @Override + public void onTaskInfoChanged(RunningTaskInfo taskInfo) { + Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId); + int winMode = getWindowingMode(taskInfo); + int prevWinMode = getWindowingMode(data.first); + if (prevWinMode != -1 && prevWinMode != winMode) { + // TODO: We currently send vanished/appeared as the task moves between win modes, but + // we should consider adding a different mode-changed callback + ArrayList<TaskListener> listeners = mListenersByWindowingMode.get(prevWinMode); + if (listeners != null) { + for (int i = listeners.size() - 1; i >= 0; i--) { + listeners.get(i).onTaskVanished(taskInfo); + } + } + listeners = mListenersByWindowingMode.get(winMode); + if (listeners != null) { + SurfaceControl leash = data.second; + for (int i = listeners.size() - 1; i >= 0; i--) { + listeners.get(i).onTaskAppeared(taskInfo, leash); + } + } + } else { + ArrayList<TaskListener> listeners = mListenersByWindowingMode.get(winMode); + if (listeners != null) { + for (int i = listeners.size() - 1; i >= 0; i--) { + listeners.get(i).onTaskInfoChanged(taskInfo); + } + } + } + } + + @Override + public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { + ArrayList<TaskListener> listeners = mListenersByWindowingMode.get( + getWindowingMode(taskInfo)); + if (listeners != null) { + for (int i = listeners.size() - 1; i >= 0; i--) { + listeners.get(i).onBackPressedOnTaskRoot(taskInfo); + } + } + } + + @Override + public void onTaskVanished(RunningTaskInfo taskInfo) { + int prevWinMode = getWindowingMode(mTasks.get(taskInfo.taskId).first); + mTasks.remove(taskInfo.taskId); + ArrayList<TaskListener> listeners = mListenersByWindowingMode.get(prevWinMode); + if (listeners != null) { + for (int i = listeners.size() - 1; i >= 0; i--) { + listeners.get(i).onTaskVanished(taskInfo); + } + } + } + + private int getWindowingMode(RunningTaskInfo taskInfo) { + return taskInfo.configuration.windowConfiguration.getWindowingMode(); + } +} diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java new file mode 100644 index 000000000000..10672c8d87ad --- /dev/null +++ b/libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -0,0 +1,121 @@ +/* + * 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 static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + +import static org.junit.Assert.assertTrue; + +import android.app.ActivityManager.RunningTaskInfo; +import android.content.res.Configuration; +import android.view.SurfaceControl; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; + +/** + * Tests for the shell task organizer. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ShellTaskOrganizerTests { + + ShellTaskOrganizer mOrganizer; + + private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener { + final ArrayList<RunningTaskInfo> appeared = new ArrayList<>(); + final ArrayList<RunningTaskInfo> vanished = new ArrayList<>(); + final ArrayList<RunningTaskInfo> infoChanged = new ArrayList<>(); + + @Override + public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { + appeared.add(taskInfo); + } + + @Override + public void onTaskInfoChanged(RunningTaskInfo taskInfo) { + infoChanged.add(taskInfo); + } + + @Override + public void onTaskVanished(RunningTaskInfo taskInfo) { + vanished.add(taskInfo); + } + + @Override + public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { + // Not currently used + } + } + + @Before + public void setUp() { + mOrganizer = new ShellTaskOrganizer(); + } + + @Test + public void testAppearedVanished() { + RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW); + TrackingTaskListener listener = new TrackingTaskListener(); + mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.onTaskAppeared(taskInfo, null); + assertTrue(listener.appeared.contains(taskInfo)); + + mOrganizer.onTaskVanished(taskInfo); + assertTrue(listener.vanished.contains(taskInfo)); + } + + @Test + public void testAddListenerExistingTasks() { + RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.onTaskAppeared(taskInfo, null); + + TrackingTaskListener listener = new TrackingTaskListener(); + mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW); + assertTrue(listener.appeared.contains(taskInfo)); + } + + @Test + public void testWindowingModeChange() { + RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW); + TrackingTaskListener mwListener = new TrackingTaskListener(); + TrackingTaskListener pipListener = new TrackingTaskListener(); + mOrganizer.addListener(mwListener, WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.addListener(pipListener, WINDOWING_MODE_PINNED); + mOrganizer.onTaskAppeared(taskInfo, null); + assertTrue(mwListener.appeared.contains(taskInfo)); + assertTrue(pipListener.appeared.isEmpty()); + + taskInfo = createTaskInfo(WINDOWING_MODE_PINNED); + mOrganizer.onTaskInfoChanged(taskInfo); + assertTrue(mwListener.vanished.contains(taskInfo)); + assertTrue(pipListener.appeared.contains(taskInfo)); + } + + private RunningTaskInfo createTaskInfo(int windowingMode) { + RunningTaskInfo taskInfo = new RunningTaskInfo(); + taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode); + return taskInfo; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 5a7772320139..2fc5cba35616 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -321,5 +321,4 @@ public class DependencyProvider { public ModeSwitchesController providesModeSwitchesController(Context context) { return new ModeSwitchesController(context); } - } diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index cfc544709725..1ea58887ddc7 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -60,6 +60,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.pip.phone.PipUpdateThread; import com.android.systemui.stackdivider.Divider; import com.android.wm.shell.R; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import java.io.PrintWriter; @@ -82,7 +83,7 @@ import java.util.function.Consumer; * see also {@link com.android.systemui.pip.phone.PipMotionHelper}. */ @SysUISingleton -public class PipTaskOrganizer extends TaskOrganizer implements +public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganizer.TaskListener, DisplayController.OnDisplaysChangedListener { private static final String TAG = PipTaskOrganizer.class.getSimpleName(); private static final boolean DEBUG = false; @@ -104,6 +105,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; private final Map<IBinder, Configuration> mInitialState = new HashMap<>(); private final Divider mSplitDivider; + protected final ShellTaskOrganizer mTaskOrganizer; // These callbacks are called on the update thread private final PipAnimationController.PipAnimationCallback mPipAnimationCallback = @@ -207,7 +209,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper, @Nullable Divider divider, @NonNull DisplayController displayController, - @NonNull PipUiEventLogger pipUiEventLogger) { + @NonNull PipUiEventLogger pipUiEventLogger, + @NonNull ShellTaskOrganizer shellTaskOrganizer) { mMainHandler = new Handler(Looper.getMainLooper()); mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks); mPipBoundsHandler = boundsHandler; @@ -218,6 +221,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements mPipUiEventLoggerLogger = pipUiEventLogger; mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; mSplitDivider = divider; + mTaskOrganizer = shellTaskOrganizer; + mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED); displayController.addDisplayWindowListener(this); } @@ -312,7 +317,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements : WINDOWING_MODE_FULLSCREEN); wct.setBounds(mToken, destinationBounds); wct.setBoundsChangeTransaction(mToken, tx); - applySyncTransaction(wct, new WindowContainerTransactionCallback() { + mTaskOrganizer.applySyncTransaction(wct, new WindowContainerTransactionCallback() { @Override public void onTransactionReady(int id, SurfaceControl.Transaction t) { t.apply(); @@ -442,7 +447,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); wct.setBounds(mToken, destinationBounds); wct.scheduleFinishEnterPip(mToken, destinationBounds); - applySyncTransaction(wct, new WindowContainerTransactionCallback() { + mTaskOrganizer.applySyncTransaction(wct, new WindowContainerTransactionCallback() { @Override public void onTransactionReady(int id, SurfaceControl.Transaction t) { t.apply(); @@ -539,11 +544,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements } @Override - public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) { - // Do nothing - } - - @Override public void onFixedRotationStarted(int displayId, int newRotation) { mShouldDeferEnteringPip = true; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index ac076415cd1a..27cc3d458062 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -60,6 +60,7 @@ import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.FloatingContentCoordinator; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; @@ -272,7 +273,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio Divider divider, FloatingContentCoordinator floatingContentCoordinator, SysUiState sysUiState, - PipUiEventLogger pipUiEventLogger) { + PipUiEventLogger pipUiEventLogger, + ShellTaskOrganizer shellTaskOrganizer) { mContext = context; mActivityManager = ActivityManager.getService(); @@ -288,7 +290,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mPipBoundsHandler = new PipBoundsHandler(mContext); mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context, configController); mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler, - mPipSurfaceTransactionHelper, divider, mDisplayController, pipUiEventLogger); + mPipSurfaceTransactionHelper, divider, mDisplayController, pipUiEventLogger, + shellTaskOrganizer); mPipTaskOrganizer.registerPipTransitionCallback(this); mInputConsumerController = InputConsumerController.getPipInputConsumer(); mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher); @@ -311,7 +314,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio configController.addCallback(mOverlayChangedListener); try { - mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED); ActivityManager.StackInfo stackInfo = ActivityTaskManager.getService().getStackInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); if (stackInfo != null) { diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index 3aef0dacad72..0531ca195f95 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -62,6 +62,7 @@ import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import java.util.ArrayList; @@ -237,7 +238,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio ConfigurationController configController, DisplayController displayController, Divider divider, - @NonNull PipUiEventLogger pipUiEventLogger) { + @NonNull PipUiEventLogger pipUiEventLogger, + ShellTaskOrganizer shellTaskOrganizer) { if (mInitialized) { return; } @@ -255,7 +257,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio .getInteger(R.integer.config_pipResizeAnimationDuration); mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context, configController); mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler, - mPipSurfaceTransactionHelper, divider, displayController, pipUiEventLogger); + mPipSurfaceTransactionHelper, divider, displayController, pipUiEventLogger, + shellTaskOrganizer); mPipTaskOrganizer.registerPipTransitionCallback(this); mActivityTaskManager = ActivityTaskManager.getService(); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); @@ -274,7 +277,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio try { WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener); - mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED); } catch (RemoteException | UnsupportedOperationException e) { Log.e(TAG, "Failed to register pinned stack listener", e); } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java index 1ee8abb411b9..9b5833b4c116 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java @@ -35,6 +35,7 @@ import android.window.WindowOrganizer; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.systemui.R; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; @@ -91,7 +92,8 @@ public class DividerController implements DisplayController.OnDisplaysChangedLis public DividerController(Context context, DisplayController displayController, SystemWindows systemWindows, - DisplayImeController imeController, Handler handler, TransactionPool transactionPool) { + DisplayImeController imeController, Handler handler, TransactionPool transactionPool, + ShellTaskOrganizer shellTaskOrganizer) { mContext = context; mDisplayController = displayController; mSystemWindows = systemWindows; @@ -100,7 +102,7 @@ public class DividerController implements DisplayController.OnDisplaysChangedLis mForcedResizableController = new ForcedResizableInfoActivityController(context, this); mTransactionPool = transactionPool; mWindowManagerProxy = new WindowManagerProxy(mTransactionPool, mHandler); - mSplits = new SplitScreenTaskOrganizer(this); + mSplits = new SplitScreenTaskOrganizer(this, shellTaskOrganizer); mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler); mRotationController = (display, fromRotation, toRotation, wct) -> { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java index 9c2139772e7d..9acb96bb45e9 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java @@ -22,6 +22,7 @@ import android.os.Handler; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.SystemWindows; @@ -39,10 +40,11 @@ public class DividerModule { @Provides static Divider provideDivider(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController imeController, @Main Handler handler, - KeyguardStateController keyguardStateController, TransactionPool transactionPool) { + KeyguardStateController keyguardStateController, TransactionPool transactionPool, + ShellTaskOrganizer shellTaskOrganizer) { // TODO(b/161116823): fetch DividerProxy from WM shell lib. DividerController dividerController = new DividerController(context, displayController, - systemWindows, imeController, handler, transactionPool); + systemWindows, imeController, handler, transactionPool, shellTaskOrganizer); return new Divider(context, dividerController, keyguardStateController); } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java index ef5e8a15882c..ffd0c7c061d6 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java @@ -33,10 +33,14 @@ import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.TaskOrganizer; -class SplitScreenTaskOrganizer extends TaskOrganizer { +import com.android.wm.shell.ShellTaskOrganizer; + +class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener { private static final String TAG = "SplitScreenTaskOrg"; private static final boolean DEBUG = DividerController.DEBUG; + private final ShellTaskOrganizer mTaskOrganizer; + RunningTaskInfo mPrimary; RunningTaskInfo mSecondary; SurfaceControl mPrimarySurface; @@ -49,13 +53,15 @@ class SplitScreenTaskOrganizer extends TaskOrganizer { final SurfaceSession mSurfaceSession = new SurfaceSession(); - SplitScreenTaskOrganizer(DividerController dividerController) { + SplitScreenTaskOrganizer(DividerController dividerController, + ShellTaskOrganizer shellTaskOrganizer) { mDividerController = dividerController; + mTaskOrganizer = shellTaskOrganizer; + mTaskOrganizer.addListener(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); } void init() throws RemoteException { - registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); synchronized (this) { try { mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, @@ -64,7 +70,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer { WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); } catch (Exception e) { // teardown to prevent callbacks - unregisterOrganizer(); + mTaskOrganizer.removeListener(this); throw e; } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 34398cc79bd2..18cb7d3b3200 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -26,6 +26,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.pip.PipUiEventLogger; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.FloatingContentCoordinator; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; @@ -77,4 +78,11 @@ public class WMShellBaseModule { return new SystemWindows(displayController, wmService); } + @SysUISingleton + @Provides + public ShellTaskOrganizer provideShellTaskOrganizer() { + ShellTaskOrganizer organizer = new ShellTaskOrganizer(); + organizer.registerOrganizer(); + return organizer; + } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 50c269e23c53..b9d7ac426348 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -783,7 +783,7 @@ class Task extends WindowContainer<WindowContainer> { * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished. */ ITaskOrganizer mTaskOrganizer; - private int mLastTaskOrganizerWindowingMode = -1; + /** * Prevent duplicate calls to onTaskAppeared. */ @@ -798,6 +798,7 @@ class Task extends WindowContainer<WindowContainer> { * organizer for ordering purposes.</li> * </ul> */ + @VisibleForTesting boolean mCreatedByOrganizer; /** @@ -4823,19 +4824,18 @@ class Task extends WindowContainer<WindowContainer> { return false; } - ITaskOrganizer previousOrganizer = mTaskOrganizer; + ITaskOrganizer prevOrganizer = mTaskOrganizer; // Update the new task organizer before calling sendTaskVanished since it could result in // a new SurfaceControl getting created that would notify the old organizer about it. mTaskOrganizer = organizer; // Let the old organizer know it has lost control. - sendTaskVanished(previousOrganizer); + sendTaskVanished(prevOrganizer); if (mTaskOrganizer != null) { sendTaskAppeared(); } else { // No longer managed by any organizer. mTaskAppearedSent = false; - mLastTaskOrganizerWindowingMode = -1; setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */); if (mCreatedByOrganizer) { removeImmediately(); @@ -4856,29 +4856,16 @@ class Task extends WindowContainer<WindowContainer> { */ boolean updateTaskOrganizerState(boolean forceUpdate) { if (!isRootTask()) { - final boolean result = setTaskOrganizer(null); - mLastTaskOrganizerWindowingMode = -1; - return result; + return setTaskOrganizer(null); } final int windowingMode = getWindowingMode(); - if (!forceUpdate && windowingMode == mLastTaskOrganizerWindowingMode) { - // If our windowing mode hasn't actually changed, then just stick - // with our old organizer. This lets us implement the semantic - // where SysUI can continue to manage it's old tasks - // while CTS temporarily takes over the registration. + final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController; + final ITaskOrganizer organizer = controller.getTaskOrganizer(windowingMode); + if (!forceUpdate && mTaskOrganizer == organizer) { return false; } - /* - * Different windowing modes may be managed by different task organizers. If - * getTaskOrganizer returns null, we still call setTaskOrganizer to - * make sure we clear it. - */ - final ITaskOrganizer org = - mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode); - final boolean result = setTaskOrganizer(org); - mLastTaskOrganizerWindowingMode = org != null ? windowingMode : -1; - return result; + return setTaskOrganizer(organizer); } @Override diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 04d134c3649d..f8465ddc02a2 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -20,6 +20,8 @@ import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS; @@ -35,7 +37,6 @@ import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; -import android.util.SparseArray; import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; @@ -46,9 +47,12 @@ import com.android.internal.util.ArrayUtils; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.WeakHashMap; import java.util.function.Consumer; @@ -58,7 +62,6 @@ import java.util.function.Consumer; */ class TaskOrganizerController extends ITaskOrganizerController.Stub { private static final String TAG = "TaskOrganizerController"; - private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>(); /** * Masks specifying which configurations are important to report back to an organizer when @@ -67,6 +70,16 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { private static final int REPORT_CONFIGS = CONTROLLABLE_CONFIGS; private static final int REPORT_WINDOW_CONFIGS = CONTROLLABLE_WINDOW_CONFIGS; + // The set of modes that are currently supports + // TODO: Remove once the task organizer can support all modes + @VisibleForTesting + static final int[] SUPPORTED_WINDOWING_MODES = { + WINDOWING_MODE_PINNED, + WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, + WINDOWING_MODE_MULTI_WINDOW, + }; + private final WindowManagerGlobalLock mGlobalLock; private class DeathRecipient implements IBinder.DeathRecipient { @@ -233,9 +246,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { void dispose() { // Move organizer from managing specific windowing modes - for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) { - mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.getBinder()); - } + mTaskOrganizers.remove(mOrganizer.mTaskOrganizer); // Update tasks currently managed by this organizer to the next one available if // possible. @@ -257,8 +268,8 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } } - private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode = - new SparseArray<>(); + // List of task organizers by priority + private final LinkedList<ITaskOrganizer> mTaskOrganizers = new LinkedList<>(); private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>(); private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>(); @@ -285,59 +296,28 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { public void setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer) { mDeferTaskOrgCallbacksConsumer = consumer; } - /** - * Register a TaskOrganizer to manage tasks as they enter the given windowing mode. - * If there was already a TaskOrganizer for this windowing mode it will be evicted - * but will continue to organize it's existing tasks. + * Register a TaskOrganizer to manage tasks as they enter the a supported windowing mode. */ @Override - public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) { - if (windowingMode == WINDOWING_MODE_PINNED) { - if (!mService.mSupportsPictureInPicture) { - throw new UnsupportedOperationException("Picture in picture is not supported on " - + "this device"); - } - } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) { - if (!mService.mSupportsSplitScreenMultiWindow) { - throw new UnsupportedOperationException("Split-screen is not supported on this " - + "device"); - } - } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) { - if (!mService.mSupportsMultiWindow) { - throw new UnsupportedOperationException("Multi-window is not supported on this " - + "device"); - } - } else { - throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow" - + " windowing modes are supported for registerTaskOrganizer"); - } + public void registerTaskOrganizer(ITaskOrganizer organizer) { enforceStackPermission("registerTaskOrganizer()"); final int uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - if (getTaskOrganizer(windowingMode) != null) { - Slog.w(TAG, "Task organizer already exists for windowing mode: " - + windowingMode); - } - - LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode); - if (orgs == null) { - orgs = new LinkedList<>(); - mTaskOrganizersForWindowingMode.put(windowingMode, orgs); - } - orgs.add(organizer.asBinder()); - if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) { - mTaskOrganizerStates.put(organizer.asBinder(), - new TaskOrganizerState(organizer, uid)); - } - - mService.mRootWindowContainer.forAllTasks((task) -> { - if (task.getWindowingMode() == windowingMode) { - task.updateTaskOrganizerState(true /* forceUpdate */); + for (int winMode : SUPPORTED_WINDOWING_MODES) { + if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) { + mTaskOrganizers.add(organizer); + mTaskOrganizerStates.put(organizer.asBinder(), + new TaskOrganizerState(organizer, uid)); } - }); + mService.mRootWindowContainer.forAllTasks((task) -> { + if (task.getWindowingMode() == winMode) { + task.updateTaskOrganizerState(true /* forceUpdate */); + } + }); + } } } finally { Binder.restoreCallingIdentity(origId); @@ -362,17 +342,22 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } } + /** + * @return the task organizer key for a given windowing mode. + */ ITaskOrganizer getTaskOrganizer(int windowingMode) { - final IBinder organizer = - mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast(); - if (organizer == null) { - return null; - } - final TaskOrganizerState state = mTaskOrganizerStates.get(organizer); - if (state == null) { - return null; + return isSupportedWindowingMode(windowingMode) + ? mTaskOrganizers.peekLast() + : null; + } + + private boolean isSupportedWindowingMode(int winMode) { + for (int i = 0; i < SUPPORTED_WINDOWING_MODES.length; i++) { + if (SUPPORTED_WINDOWING_MODES[i] == winMode) { + return true; + } } - return state.mOrganizer.mTaskOrganizer; + return false; } void onTaskAppeared(ITaskOrganizer organizer, Task task) { @@ -458,6 +443,8 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { || mTmpTaskInfo.topActivityType != lastInfo.topActivityType || mTmpTaskInfo.isResizeable != lastInfo.isResizeable || mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams + || mTmpTaskInfo.getConfiguration().windowConfiguration.getWindowingMode() + != lastInfo.getConfiguration().windowConfiguration.getWindowingMode() || !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription); if (!changed) { int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration); @@ -655,18 +642,19 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { final String innerPrefix = prefix + " "; pw.print(prefix); pw.println("TaskOrganizerController:"); pw.print(innerPrefix); pw.println("Per windowing mode:"); - for (int i = 0; i < mTaskOrganizersForWindowingMode.size(); i++) { - final int windowingMode = mTaskOrganizersForWindowingMode.keyAt(i); - final List<IBinder> taskOrgs = mTaskOrganizersForWindowingMode.valueAt(i); + for (int i = 0; i < SUPPORTED_WINDOWING_MODES.length; i++) { + final int windowingMode = SUPPORTED_WINDOWING_MODES[i]; pw.println(innerPrefix + " " + WindowConfiguration.windowingModeToString(windowingMode) + ":"); - for (int j = 0; j < taskOrgs.size(); j++) { - final TaskOrganizerState state = mTaskOrganizerStates.get(taskOrgs.get(j)); + for (final TaskOrganizerState state : mTaskOrganizerStates.values()) { final ArrayList<Task> tasks = state.mOrganizedTasks; pw.print(innerPrefix + " "); pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":"); for (int k = 0; k < tasks.size(); k++) { - pw.println(innerPrefix + " " + tasks.get(k)); + final Task task = tasks.get(k); + if (windowingMode == task.getWindowingMode()) { + pw.println(innerPrefix + " " + task); + } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 91352972e772..289d54e967f5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -88,20 +88,14 @@ import java.util.List; @Presubmit @RunWith(WindowTestRunner.class) public class WindowOrganizerTests extends WindowTestsBase { - private ITaskOrganizer registerMockOrganizer(int windowingMode) { + private ITaskOrganizer registerMockOrganizer() { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); when(organizer.asBinder()).thenReturn(new Binder()); - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer( - organizer, windowingMode); - + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(organizer); return organizer; } - private ITaskOrganizer registerMockOrganizer() { - return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); - } - Task createTask(Task stack, boolean fakeDraw) { final Task task = createTaskInStack(stack, 0); @@ -133,11 +127,12 @@ public class WindowOrganizerTests extends WindowTestsBase { final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(); - task.setTaskOrganizer(organizer); + stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + stack.setTaskOrganizer(organizer); verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.removeImmediately(); + stack.removeImmediately(); verify(organizer).onTaskVanished(any()); } @@ -147,16 +142,17 @@ public class WindowOrganizerTests extends WindowTestsBase { final Task task = createTask(stack, false); final ITaskOrganizer organizer = registerMockOrganizer(); - task.setTaskOrganizer(organizer); + stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + stack.setTaskOrganizer(organizer); verify(organizer, never()) .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.setHasBeenVisible(true); + stack.setHasBeenVisible(true); assertTrue(stack.getHasBeenVisible()); verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.removeImmediately(); + stack.removeImmediately(); verify(organizer).onTaskVanished(any()); } @@ -169,42 +165,14 @@ public class WindowOrganizerTests extends WindowTestsBase { // In this test we skip making the Task visible, and verify // that even though a TaskOrganizer is set remove doesn't emit // a vanish callback, because we never emitted appear. - task.setTaskOrganizer(organizer); + stack.setTaskOrganizer(organizer); verify(organizer, never()) .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.removeImmediately(); + stack.removeImmediately(); verify(organizer, never()).onTaskVanished(any()); } @Test - public void testSwapOrganizer() throws RemoteException { - final Task stack = createStack(); - final Task task = createTask(stack); - final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); - final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED); - - task.setTaskOrganizer(organizer); - verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.setTaskOrganizer(organizer2); - verify(organizer).onTaskVanished(any()); - verify(organizer2).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - } - - @Test - public void testSwapWindowingModes() throws RemoteException { - final Task stack = createStack(); - final Task task = createTask(stack); - final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); - final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED); - - stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); - verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - stack.setWindowingMode(WINDOWING_MODE_PINNED); - verify(organizer).onTaskVanished(any()); - verify(organizer2).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - } - - @Test public void testTaskNoDraw() throws RemoteException { final Task stack = createStack(); final Task task = createTask(stack, false /* fakeDraw */); @@ -226,6 +194,7 @@ public class WindowOrganizerTests extends WindowTestsBase { final Task task = createTask(stack); final ITaskOrganizer organizer = registerMockOrganizer(); + stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); stack.setTaskOrganizer(organizer); verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); assertTrue(stack.isOrganized()); @@ -258,7 +227,7 @@ public class WindowOrganizerTests extends WindowTestsBase { final Task task2 = createTask(stack2); final Task stack3 = createStack(); final Task task3 = createTask(stack3); - final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); + final ITaskOrganizer organizer = registerMockOrganizer(); // First organizer is registered, verify a task appears when changing windowing mode stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); @@ -268,7 +237,7 @@ public class WindowOrganizerTests extends WindowTestsBase { // Now we replace the registration and1 verify the new organizer receives tasks // newly entering the windowing mode. - final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); + final ITaskOrganizer organizer2 = registerMockOrganizer(); stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); // One each for task and task2 verify(organizer2, times(2)) @@ -294,7 +263,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException { - final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED); + final ITaskOrganizer organizer = registerMockOrganizer(); final Task stack = createStack(); final Task task = createTask(stack); @@ -313,7 +282,7 @@ public class WindowOrganizerTests extends WindowTestsBase { final Task task = createTask(stack); stack.setWindowingMode(WINDOWING_MODE_PINNED); - final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED); + final ITaskOrganizer organizer = registerMockOrganizer(); verify(organizer, times(1)) .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); } @@ -483,8 +452,7 @@ public class WindowOrganizerTests extends WindowTestsBase { public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } }; - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener, - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); @@ -542,8 +510,7 @@ public class WindowOrganizerTests extends WindowTestsBase { public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } }; - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener, - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); lastReportedTiles.clear(); @@ -604,10 +571,7 @@ public class WindowOrganizerTests extends WindowTestsBase { public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } }; - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer( - listener, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer( - listener, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask( @@ -874,7 +838,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testEnterPipParams() { final StubOrganizer o = new StubOrganizer(); - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED); + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o); final ActivityRecord record = makePipableActivity(); final PictureInPictureParams p = new PictureInPictureParams.Builder() @@ -895,7 +859,7 @@ public class WindowOrganizerTests extends WindowTestsBase { } } ChangeSavingOrganizer o = new ChangeSavingOrganizer(); - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED); + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o); final ActivityRecord record = makePipableActivity(); final PictureInPictureParams p = new PictureInPictureParams.Builder() @@ -926,8 +890,7 @@ public class WindowOrganizerTests extends WindowTestsBase { } } ChangeSavingOrganizer o = new ChangeSavingOrganizer(); - mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, - WINDOWING_MODE_MULTI_WINDOW); + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o); final Task stack = createStack(); final Task task = createTask(stack); @@ -942,22 +905,23 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testPreventDuplicateAppear() throws RemoteException { final Task stack = createStack(); - final Task task = createTask(stack); + final Task task = createTask(stack, false /* fakeDraw */); final ITaskOrganizer organizer = registerMockOrganizer(); - task.setTaskOrganizer(organizer); + stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + stack.setTaskOrganizer(organizer); // setHasBeenVisible was already called once by the set-up code. - task.setHasBeenVisible(true); + stack.setHasBeenVisible(true); verify(organizer, times(1)) .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.setTaskOrganizer(null); + stack.setTaskOrganizer(null); verify(organizer, times(1)).onTaskVanished(any()); - task.setTaskOrganizer(organizer); + stack.setTaskOrganizer(organizer); verify(organizer, times(2)) .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); - task.removeImmediately(); + stack.removeImmediately(); verify(organizer, times(2)).onTaskVanished(any()); } @@ -966,7 +930,7 @@ public class WindowOrganizerTests extends WindowTestsBase { final Task stack = createStack(); final Task task = createTask(stack); final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task); - final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); + final ITaskOrganizer organizer = registerMockOrganizer(); // Setup the task to be controlled by the MW mode organizer stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 5ce61b4e4916..f86d8f15353e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -1031,10 +1031,7 @@ class WindowTestsBase extends SystemServiceTestsBase { TestSplitOrganizer(ActivityTaskManagerService service, int displayId) { mService = service; mDisplayId = displayId; - mService.mTaskOrganizerController.registerTaskOrganizer(this, - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - mService.mTaskOrganizerController.registerTaskOrganizer(this, - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mService.mTaskOrganizerController.registerTaskOrganizer(this); WindowContainerToken primary = mService.mTaskOrganizerController.createRootTask( displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token; mPrimary = WindowContainer.fromBinder(primary.asBinder()).asTask(); diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java index 073ae30aaf1a..ca723b881bbd 100644 --- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java @@ -157,7 +157,7 @@ public class TaskOrganizerMultiWindowTest extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.registerOrganizer(); mTaskView1 = new ResizingTaskView(this, makeSettingsIntent()); mTaskView2 = new ResizingTaskView(this, makeContactsIntent()); diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java index 8fc5c5d78b60..5ec949391181 100644 --- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java @@ -57,7 +57,7 @@ public class TaskOrganizerPipTest extends Service { public void onCreate() { super.onCreate(); - mOrganizer.registerOrganizer(WINDOWING_MODE_PINNED); + mOrganizer.registerOrganizer(); final WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(); wlp.setTitle("TaskOrganizerPipTest"); |