diff options
21 files changed, 689 insertions, 460 deletions
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java index c9673f59183a..1b941defba42 100644 --- a/core/java/android/app/ActivityTaskManager.java +++ b/core/java/android/app/ActivityTaskManager.java @@ -30,7 +30,6 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Singleton; -import android.window.ITaskOrganizerController; import java.util.List; @@ -159,24 +158,6 @@ public class ActivityTaskManager { } }; - /** @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public static ITaskOrganizerController getTaskOrganizerController() { - return ITaskOrganizerControllerSingleton.get(); - } - - private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton = - new Singleton<ITaskOrganizerController>() { - @Override - protected ITaskOrganizerController create() { - try { - return getService().getTaskOrganizerController(); - } catch (RemoteException e) { - return null; - } - } - }; - /** * Sets the windowing mode for a specific task. Only works on tasks of type * {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index ab5c6788969a..03717ecd4038 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -29,7 +29,6 @@ import android.app.IProcessObserver; import android.app.IRequestFinishCallback; import android.app.IServiceConnection; import android.app.IStopUserCallback; -import android.window.ITaskOrganizerController; import android.app.ITaskStackListener; import android.app.IUiAutomationConnection; import android.app.IUidObserver; @@ -69,9 +68,9 @@ import android.os.StrictMode; import android.os.WorkSource; import android.service.voice.IVoiceInteractionSession; import android.view.IRecentsAnimationRunner; -import android.window.ITaskOrganizer; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationAdapter; +import android.window.IWindowOrganizerController; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IKeyguardDismissCallback; @@ -340,10 +339,8 @@ interface IActivityTaskManager { in Rect tempDockedTaskInsetBounds, in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds); - /** - * Returns an interface enabling the management of task organizers. - */ - ITaskOrganizerController getTaskOrganizerController(); + /** Returns an interface enabling the management of window organizers. */ + IWindowOrganizerController getWindowOrganizerController(); /** * Sets whether we are currently in an interactive split screen resize operation where we diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl index b2da23949005..0a04462c4209 100644 --- a/core/java/android/window/ITaskOrganizer.aidl +++ b/core/java/android/window/ITaskOrganizer.aidl @@ -1,19 +1,18 @@ -/* //device/java/android/android/view/ITaskOrganizer.aidl -** -** Copyright 2019, 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. -*/ +/* + * Copyright (C) 2019 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 android.window; @@ -30,12 +29,6 @@ oneway interface ITaskOrganizer { void taskVanished(in ActivityManager.RunningTaskInfo taskInfo); /** - * Called upon completion of - * ActivityTaskManagerService#applyTaskOrganizerTransaction - */ - void transactionReady(int id, in SurfaceControl.Transaction t); - - /** * Will fire when core attributes of a Task's info change. Relevant properties include the * {@link WindowConfiguration.ActivityType} and whether it is resizable. * diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl index e8af8e196bed..a8b6aae80dce 100644 --- a/core/java/android/window/ITaskOrganizerController.aidl +++ b/core/java/android/window/ITaskOrganizerController.aidl @@ -36,20 +36,6 @@ interface ITaskOrganizerController { */ void unregisterTaskOrganizer(ITaskOrganizer organizer); - /** - * Apply multiple WindowContainer operations at once. - * @param organizer If non-null this transaction will use the synchronization - * scheme described in BLASTSyncEngine.java. The SurfaceControl transaction - * containing the effects of this WindowContainer transaction will be passed - * to the organizers Transaction ready callback. If null the transaction - * will apply with non particular synchronization constraints (other than - * it will all apply at once). - * @return If organizer was non-null returns an ID for the sync operation which will - * later be passed to transactionReady. This lets TaskOrganizer implementations - * differentiate overlapping sync operations. - */ - int applyContainerTransaction(in WindowContainerTransaction t, ITaskOrganizer organizer); - /** Creates a persistent root task in WM for a particular windowing-mode. */ ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode); diff --git a/core/java/android/window/IWindowContainerTransactionCallback.aidl b/core/java/android/window/IWindowContainerTransactionCallback.aidl new file mode 100644 index 000000000000..0579932f0c5f --- /dev/null +++ b/core/java/android/window/IWindowContainerTransactionCallback.aidl @@ -0,0 +1,28 @@ +/* + * 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 android.window; + +import android.view.SurfaceControl; + +/** + * See WindowOrganizer#applyTransaction. + * {@hide} + */ +oneway interface IWindowContainerTransactionCallback { + /** Called upon completion of WindowOrganizer#applyTransaction */ + void transactionReady(int id, in SurfaceControl.Transaction t); +} diff --git a/core/java/android/window/IWindowOrganizerController.aidl b/core/java/android/window/IWindowOrganizerController.aidl new file mode 100644 index 000000000000..4b47924dc5a6 --- /dev/null +++ b/core/java/android/window/IWindowOrganizerController.aidl @@ -0,0 +1,46 @@ +/** + * 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 android.window; + +import android.window.ITaskOrganizerController; +import android.window.IWindowContainerTransactionCallback; +import android.window.WindowContainerTransaction; + +/** @hide */ +interface IWindowOrganizerController { + + /** + * Apply multiple WindowContainer operations at once. + * @param t The transaction to apply. + */ + void applyTransaction(in WindowContainerTransaction t); + + /** + * Apply multiple WindowContainer operations at once. + * @param t The transaction to apply. + * @param callback This transaction will use the synchronization scheme described in + * BLASTSyncEngine.java. The SurfaceControl transaction containing the effects of this + * WindowContainer transaction will be passed to this callback when ready. + * @return An ID for the sync operation which will later be passed to transactionReady callback. + * This lets the caller differentiate overlapping sync operations. + */ + int applySyncTransaction(in WindowContainerTransaction t, + in IWindowContainerTransactionCallback callback); + + /** @return An interface enabling the management of task organizers. */ + ITaskOrganizerController getTaskOrganizerController(); +} diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java new file mode 100644 index 000000000000..b8969c162309 --- /dev/null +++ b/core/java/android/window/WindowOrganizer.java @@ -0,0 +1,157 @@ +/* + * 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 android.window; + +import android.annotation.RequiresPermission; +import android.app.ActivityManager; +import android.app.ActivityTaskManager; +import android.os.RemoteException; +import android.util.Singleton; + +import java.util.List; + +/** + * Class for organizing specific types of windows like Tasks and DisplayAreas + * + * @hide + */ +public class WindowOrganizer { + + /** + * Apply multiple WindowContainer operations at once. + * @param t The transaction to apply. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static void applyTransaction(WindowContainerTransaction t) throws RemoteException { + getWindowOrganizerController().applyTransaction(t); + } + + /** + * Apply multiple WindowContainer operations at once. + * @param t The transaction to apply. + * @param callback This transaction will use the synchronization scheme described in + * BLASTSyncEngine.java. The SurfaceControl transaction containing the effects of this + * WindowContainer transaction will be passed to this callback when ready. + * @return An ID for the sync operation which will later be passed to transactionReady callback. + * This lets the caller differentiate overlapping sync operations. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static int applySyncTransaction(WindowContainerTransaction t, + IWindowContainerTransactionCallback callback) throws RemoteException { + return getWindowOrganizerController().applySyncTransaction(t, callback); + } + + /** @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + private static IWindowOrganizerController getWindowOrganizerController() { + return IWindowOrganizerControllerSingleton.get(); + } + + private static final Singleton<IWindowOrganizerController> IWindowOrganizerControllerSingleton = + new Singleton<IWindowOrganizerController>() { + @Override + protected IWindowOrganizerController create() { + try { + return ActivityTaskManager.getService().getWindowOrganizerController(); + } catch (RemoteException e) { + return null; + } + } + }; + + public static class TaskOrganizer { + + /** + * 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. + */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static void registerOrganizer(ITaskOrganizer organizer, int windowingMode) + throws RemoteException { + getController().registerTaskOrganizer(organizer, windowingMode); + } + + /** Unregisters a previously registered task organizer. */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static void unregisterOrganizer(ITaskOrganizer organizer) throws RemoteException { + getController().unregisterTaskOrganizer(organizer); + } + + /** Creates a persistent root task in WM for a particular windowing-mode. */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static ActivityManager.RunningTaskInfo createRootTask( + int displayId, int windowingMode) throws RemoteException { + return getController().createRootTask(displayId, windowingMode); + } + + /** Deletes a persistent root task in WM */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static boolean deleteRootTask(IWindowContainer task) throws RemoteException { + return getController().deleteRootTask(task); + } + + /** Gets direct child tasks (ordered from top-to-bottom) */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static List<ActivityManager.RunningTaskInfo> getChildTasks(IWindowContainer parent, + int[] activityTypes) throws RemoteException { + return getController().getChildTasks(parent, activityTypes); + } + + /** Gets all root tasks on a display (ordered from top-to-bottom) */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static List<ActivityManager.RunningTaskInfo> getRootTasks( + int displayId, int[] activityTypes) throws RemoteException { + return getController().getRootTasks(displayId, activityTypes); + } + + /** Get the root task which contains the current ime target */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static IWindowContainer getImeTarget(int display) throws RemoteException { + return getController().getImeTarget(display); + } + + /** + * Set's the root task to launch new tasks into on a display. {@code null} means no launch + * root and thus new tasks just end up directly on the display. + */ + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) + public static void setLaunchRoot(int displayId, IWindowContainer root) + throws RemoteException { + getController().setLaunchRoot(displayId, root); + } + + private static ITaskOrganizerController getController() { + return ITaskOrganizerControllerSingleton.get(); + } + + private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton = + new Singleton<ITaskOrganizerController>() { + @Override + protected ITaskOrganizerController create() { + try { + return getWindowOrganizerController().getTaskOrganizerController(); + } catch (RemoteException e) { + return null; + } + } + }; + + } +} diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index e64a9190ae91..c28705575e86 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -42,6 +42,7 @@ import android.window.ITaskOrganizer; import android.window.IWindowContainer; import android.view.SurfaceControl; import android.window.WindowContainerTransaction; +import android.window.WindowOrganizer; import com.android.internal.os.SomeArgs; import com.android.systemui.R; @@ -76,7 +77,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private final Handler mMainHandler; private final Handler mUpdateHandler; - private final ITaskOrganizerController mTaskOrganizerController; private final PipBoundsHandler mPipBoundsHandler; private final PipAnimationController mPipAnimationController; private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>(); @@ -188,7 +188,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper) { mMainHandler = new Handler(Looper.getMainLooper()); mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks); - mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController(); mPipBoundsHandler = boundsHandler; mEnterExitAnimationDuration = context.getResources() .getInteger(R.integer.config_pipResizeAnimationDuration); @@ -265,10 +264,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } @Override - public void transactionReady(int id, SurfaceControl.Transaction t) { - } - - @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { final PictureInPictureParams newParams = info.pictureInPictureParams; if (!shouldUpdateDestinationBounds(newParams)) { @@ -450,7 +445,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { wct.setBounds(mToken, taskBounds); } wct.setBoundsChangeTransaction(mToken, tx); - mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */); + WindowOrganizer.applyTransaction(wct); } catch (RemoteException e) { Log.e(TAG, "Failed to apply container transaction", e); } 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 a0dff3f98173..e89ce2e3a56f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -18,6 +18,7 @@ package com.android.systemui.pip.phone; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.window.WindowOrganizer.TaskOrganizer; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -35,6 +36,7 @@ import android.util.Pair; import android.view.DisplayInfo; import android.view.IPinnedStackController; import android.window.WindowContainerTransaction; +import android.window.WindowOrganizer; import com.android.systemui.Dependency; import com.android.systemui.UiOffloadThread; @@ -248,8 +250,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mPipBoundsHandler.onDisplayInfoChanged(displayInfo); try { - ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer( - mPipTaskOrganizer, WINDOWING_MODE_PINNED); + TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED); ActivityManager.StackInfo stackInfo = activityTaskManager.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 050acd5a8728..2dcf1f89c3ec 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -19,6 +19,7 @@ package com.android.systemui.pip.tv; import static android.app.ActivityTaskManager.INVALID_STACK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.window.WindowOrganizer.TaskOrganizer; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackInfo; @@ -44,6 +45,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.DisplayInfo; +import android.window.WindowOrganizer; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -293,8 +295,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio try { WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener); - ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer( - mPipTaskOrganizer, WINDOWING_MODE_PINNED); + TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED); } catch (RemoteException e) { Log.e(TAG, "Failed to register pinned stack listener", e); } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 3d5281247f63..01498f933383 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -20,11 +20,11 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; +import static android.window.WindowOrganizer.TaskOrganizer; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; -import android.app.ActivityTaskManager; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; @@ -38,6 +38,7 @@ import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.View; import android.window.WindowContainerTransaction; +import android.window.WindowOrganizer; import androidx.annotation.Nullable; @@ -177,8 +178,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, private boolean getSecondaryHasFocus(int displayId) { try { - IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() - .getImeTarget(displayId); + IWindowContainer imeSplit = TaskOrganizer.getImeTarget(displayId); return imeSplit != null && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); } catch (RemoteException e) { @@ -267,8 +267,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED); } try { - ActivityTaskManager.getTaskOrganizerController() - .applyContainerTransaction(wct, null /* organizer */); + WindowOrganizer.applyTransaction(wct); } catch (RemoteException e) { } @@ -474,13 +473,12 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mImeController.addPositionProcessor(mImePositionProcessor); mDisplayController.addDisplayChangingController(mRotationController); try { - mSplits.init(ActivityTaskManager.getTaskOrganizerController(), mSurfaceSession); + mSplits.init(mSurfaceSession); // Set starting tile bounds based on middle target final WindowContainerTransaction tct = new WindowContainerTransaction(); int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; mSplitLayout.resizeSplits(midPos, tct); - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(tct, - null /* organizer */); + WindowOrganizer.applyTransaction(tct); } catch (Exception e) { Slog.e(TAG, "Failed to register docked stack listener", e); } @@ -499,8 +497,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, final WindowContainerTransaction tct = new WindowContainerTransaction(); mSplitLayout.resizeSplits(midPos, tct); try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(tct, - null /* organizer */); + WindowOrganizer.applyTransaction(tct); } catch (RemoteException e) { } } else if (mRotateSplitLayout != null diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java index f82936a4492b..8bbb548b0ecf 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java @@ -22,9 +22,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.view.Display.DEFAULT_DISPLAY; +import static android.window.WindowOrganizer.TaskOrganizer; import android.app.ActivityManager.RunningTaskInfo; -import android.window.ITaskOrganizerController; import android.app.WindowConfiguration; import android.os.RemoteException; import android.util.Log; @@ -49,13 +49,12 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub { mDivider = divider; } - void init(ITaskOrganizerController organizerController, SurfaceSession session) - throws RemoteException { - organizerController.registerTaskOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - organizerController.registerTaskOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - mPrimary = organizerController.createRootTask(Display.DEFAULT_DISPLAY, + void init(SurfaceSession session) throws RemoteException { + TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - mSecondary = organizerController.createRootTask(Display.DEFAULT_DISPLAY, + mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); mPrimarySurface = mPrimary.token.getLeash(); mSecondarySurface = mSecondary.token.getLeash(); @@ -91,10 +90,6 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub { } @Override - public void transactionReady(int id, SurfaceControl.Transaction t) { - } - - @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo) { if (taskInfo.displayId != DEFAULT_DISPLAY) { return; diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index 0e391ec7580a..8724e490a558 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; +import static android.window.WindowOrganizer.TaskOrganizer; import android.annotation.NonNull; import android.app.ActivityManager; @@ -31,6 +32,7 @@ import android.view.Display; import android.window.IWindowContainer; import android.window.WindowContainerTransaction; import android.view.WindowManagerGlobal; +import android.window.WindowOrganizer; import com.android.internal.annotations.GuardedBy; @@ -111,8 +113,7 @@ public class WindowManagerProxy { WindowContainerTransaction t = new WindowContainerTransaction(); splitLayout.resizeSplits(position, t); try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(t, - null /* organizer */); + WindowOrganizer.applyTransaction(t); } catch (RemoteException e) { } } @@ -122,10 +123,8 @@ public class WindowManagerProxy { boolean resizable = false; try { List<ActivityManager.RunningTaskInfo> rootTasks = parent == null - ? ActivityTaskManager.getTaskOrganizerController().getRootTasks( - Display.DEFAULT_DISPLAY, HOME_AND_RECENTS) - : ActivityTaskManager.getTaskOrganizerController().getChildTasks(parent, - HOME_AND_RECENTS); + ? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS) + : TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS); for (int i = 0, n = rootTasks.size(); i < n; ++i) { final ActivityManager.RunningTaskInfo ti = rootTasks.get(i); out.add(ti.token); @@ -174,11 +173,9 @@ public class WindowManagerProxy { // Set launchtile first so that any stack created after // getAllStackInfos and before reparent (even if unlikely) are placed // correctly. - ActivityTaskManager.getTaskOrganizerController().setLaunchRoot( - DEFAULT_DISPLAY, tiles.mSecondary.token); + TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token); List<ActivityManager.RunningTaskInfo> rootTasks = - ActivityTaskManager.getTaskOrganizerController().getRootTasks(DEFAULT_DISPLAY, - null /* activityTypes */); + TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */); WindowContainerTransaction wct = new WindowContainerTransaction(); if (rootTasks.isEmpty()) { return false; @@ -192,8 +189,7 @@ public class WindowManagerProxy { true /* onTop */); } boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct); - ActivityTaskManager.getTaskOrganizerController() - .applyContainerTransaction(wct, null /* organizer */); + WindowOrganizer.applyTransaction(wct); return isHomeResizable; } catch (RemoteException e) { Log.w(TAG, "Error moving fullscreen tasks to secondary split: " + e); @@ -216,22 +212,18 @@ public class WindowManagerProxy { try { // Set launch root first so that any task created after getChildContainers and // before reparent (pretty unlikely) are put into fullscreen. - ActivityTaskManager.getTaskOrganizerController().setLaunchRoot(Display.DEFAULT_DISPLAY, - null); + TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null); // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished // plus specific APIs to clean this up. List<ActivityManager.RunningTaskInfo> primaryChildren = - ActivityTaskManager.getTaskOrganizerController().getChildTasks( - tiles.mPrimary.token, null /* activityTypes */); + TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */); List<ActivityManager.RunningTaskInfo> secondaryChildren = - ActivityTaskManager.getTaskOrganizerController().getChildTasks( - tiles.mSecondary.token, null /* activityTypes */); + TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */); // In some cases (eg. non-resizable is launched), system-server will leave split-screen. // as a result, the above will not capture any tasks; yet, we need to clean-up the // home task bounds. List<ActivityManager.RunningTaskInfo> freeHomeAndRecents = - ActivityTaskManager.getTaskOrganizerController().getRootTasks( - Display.DEFAULT_DISPLAY, HOME_AND_RECENTS); + TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS); if (primaryChildren.isEmpty() && secondaryChildren.isEmpty() && freeHomeAndRecents.isEmpty()) { return; @@ -281,8 +273,7 @@ public class WindowManagerProxy { } // Reset focusable to true wct.setFocusable(tiles.mPrimary.token, true /* focusable */); - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, - null /* organizer */); + WindowOrganizer.applyTransaction(wct); } catch (RemoteException e) { Log.w(TAG, "Failed to remove stack: " + e); } @@ -290,8 +281,7 @@ public class WindowManagerProxy { static void applyContainerTransaction(WindowContainerTransaction wct) { try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, - null /* organizer */); + WindowOrganizer.applyTransaction(wct); } catch (RemoteException e) { Log.w(TAG, "Error setting focusability: " + e); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 184439587a02..f7278e70cede 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -230,6 +230,7 @@ import android.util.proto.ProtoOutputStream; import android.view.IRecentsAnimationRunner; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationDefinition; +import android.window.IWindowOrganizerController; import android.window.WindowContainerTransaction; import android.view.WindowManager; @@ -663,10 +664,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private FontScaleSettingObserver mFontScaleSettingObserver; - /** - * Stores the registration and state of TaskOrganizers in use. - */ - TaskOrganizerController mTaskOrganizerController = new TaskOrganizerController(this); + WindowOrganizerController mWindowOrganizerController; + TaskOrganizerController mTaskOrganizerController; private int mDeviceOwnerUid = Process.INVALID_UID; @@ -724,6 +723,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mLifecycleManager = new ClientLifecycleManager(); mInternal = new LocalService(); GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED); + mWindowOrganizerController = new WindowOrganizerController(this); + mTaskOrganizerController = mWindowOrganizerController.mTaskOrganizerController; } public void onSystemReady() { @@ -2772,7 +2773,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reparent(stack.mRemoteToken, tile.mRemoteToken, toTop); - mTaskOrganizerController.applyContainerTransaction(wct, null); + mWindowOrganizerController.applyTransaction(wct); } /** @@ -4311,7 +4312,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } wct.setBounds(secondary.mRemoteToken, otherRect); - mTaskOrganizerController.applyContainerTransaction(wct, null /* organizer */); + mWindowOrganizerController.applyTransaction(wct); } } finally { Binder.restoreCallingIdentity(ident); @@ -4332,10 +4333,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ITaskOrganizerController getTaskOrganizerController() { + public IWindowOrganizerController getWindowOrganizerController() { mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, - "getTaskOrganizerController()"); - return mTaskOrganizerController; + "getWindowOrganizerController()"); + return mWindowOrganizerController; } /** diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 776a9863dc6a..60b817c13236 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -531,8 +531,7 @@ public class DisplayRotation { try { mDisplayContent.sendNewConfiguration(); if (t != null) { - mService.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, - null /* organizer */); + mService.mAtmService.mWindowOrganizerController.applyTransaction(t); } } finally { mService.mAtmService.continueWindowLayout(); diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 9bf4d6355071..fc58ee785cf8 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -22,59 +22,34 @@ 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.ActivityStackSupervisor.PRESERVE_WINDOWS; -import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG; -import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; -import static com.android.server.wm.WindowContainer.POSITION_TOP; +import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS; +import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; -import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; -import android.util.ArraySet; import android.util.Slog; -import android.view.SurfaceControl; import android.window.ITaskOrganizerController; import android.window.ITaskOrganizer; import android.window.IWindowContainer; -import android.window.WindowContainerTransaction; import com.android.internal.util.ArrayUtils; -import com.android.internal.util.function.pooled.PooledConsumer; -import com.android.internal.util.function.pooled.PooledLambda; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.WeakHashMap; /** * Stores the TaskOrganizers associated with a given windowing mode and * their associated state. */ -class TaskOrganizerController extends ITaskOrganizerController.Stub - implements BLASTSyncEngine.TransactionReadyListener { +class TaskOrganizerController extends ITaskOrganizerController.Stub { private static final String TAG = "TaskOrganizerController"; - /** Flag indicating that an applied transaction may have effected lifecycle */ - private static final int TRANSACT_EFFECTS_CLIENT_CONFIG = 1; - private static final int TRANSACT_EFFECTS_LIFECYCLE = 1 << 1; - - /** - * Masks specifying which configurations task-organizers can control. Incoming transactions - * will be filtered to only include these. - */ - private static final int CONTROLLABLE_CONFIGS = ActivityInfo.CONFIG_WINDOW_CONFIGURATION - | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE; - private static final int CONTROLLABLE_WINDOW_CONFIGS = WindowConfiguration.WINDOW_CONFIG_BOUNDS - | WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; /** * Masks specifying which configurations are important to report back to an organizer when * changed. @@ -181,13 +156,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub final HashMap<Integer, TaskOrganizerState> mTaskOrganizersForWindowingMode = new HashMap(); final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap(); - final HashMap<Integer, ITaskOrganizer> mTaskOrganizersByPendingSyncId = new HashMap(); - private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>(); - private final BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine(); - final ActivityTaskManagerService mService; RunningTaskInfo mTmpTaskInfo; @@ -498,253 +469,4 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub Binder.restoreCallingIdentity(ident); } } - - private int sanitizeAndApplyChange(WindowContainer container, - WindowContainerTransaction.Change change) { - if (!(container instanceof Task)) { - throw new RuntimeException("Invalid token in task transaction"); - } - final Task task = (Task) container; - // The "client"-facing API should prevent bad changes; however, just in case, sanitize - // masks here. - final int configMask = change.getConfigSetMask() & CONTROLLABLE_CONFIGS; - final int windowMask = change.getWindowSetMask() & CONTROLLABLE_WINDOW_CONFIGS; - int effects = 0; - if (configMask != 0) { - Configuration c = new Configuration(container.getRequestedOverrideConfiguration()); - c.setTo(change.getConfiguration(), configMask, windowMask); - container.onRequestedOverrideConfigurationChanged(c); - // TODO(b/145675353): remove the following once we could apply new bounds to the - // pinned stack together with its children. - resizePinnedStackIfNeeded(container, configMask, windowMask, c); - effects |= TRANSACT_EFFECTS_CLIENT_CONFIG; - } - if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_FOCUSABLE) != 0) { - if (container.setFocusable(change.getFocusable())) { - effects |= TRANSACT_EFFECTS_LIFECYCLE; - } - } - if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) { - if (task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, change.getHidden())) { - effects |= TRANSACT_EFFECTS_LIFECYCLE; - } - } - return effects; - } - - private int sanitizeAndApplyHierarchyOp(WindowContainer container, - WindowContainerTransaction.HierarchyOp hop) { - if (!(container instanceof Task)) { - throw new IllegalArgumentException("Invalid container in hierarchy op"); - } - if (container.getDisplayContent() == null) { - Slog.w(TAG, "Container is no longer attached: " + container); - return 0; - } - if (hop.isReparent()) { - // special case for tiles since they are "virtual" parents - if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) { - ActivityStack as = (ActivityStack) container; - TaskTile newParent = hop.getNewParent() == null ? null - : (TaskTile) WindowContainer.fromBinder(hop.getNewParent()); - if (as.getTile() != newParent) { - if (as.getTile() != null) { - as.getTile().removeChild(as); - } - if (newParent != null) { - if (!as.affectedBySplitScreenResize()) { - return 0; - } - newParent.addChild(as, POSITION_TOP); - } - } - if (hop.getToTop()) { - as.getDisplay().positionStackAtTop(as, false /* includingParents */); - } else { - as.getDisplay().positionStackAtBottom(as); - } - } else if (container instanceof Task) { - throw new RuntimeException("Reparenting leaf Tasks is not supported now."); - } - } else { - // Ugh, of course ActivityStack has its own special reorder logic... - if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) { - ActivityStack as = (ActivityStack) container; - if (hop.getToTop()) { - as.getDisplay().positionStackAtTop(as, false /* includingParents */); - } else { - as.getDisplay().positionStackAtBottom(as); - } - } else { - container.getParent().positionChildAt( - hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM, - container, false /* includingParents */); - } - } - return TRANSACT_EFFECTS_LIFECYCLE; - } - - private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask, - int windowMask, Configuration config) { - if ((container instanceof ActivityStack) - && ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) - && ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) { - final ActivityStack stack = (ActivityStack) container; - if (stack.inPinnedWindowingMode()) { - stack.resize(config.windowConfiguration.getBounds(), - null /* configBounds */, PRESERVE_WINDOWS, true /* deferResume */); - } - } - } - - private int applyWindowContainerChange(WindowContainer wc, - WindowContainerTransaction.Change c) { - int effects = sanitizeAndApplyChange(wc, c); - - final Task tr = wc.asTask(); - - final SurfaceControl.Transaction t = c.getBoundsChangeTransaction(); - if (t != null) { - tr.setMainWindowSizeChangeTransaction(t); - } - - Rect enterPipBounds = c.getEnterPipBounds(); - if (enterPipBounds != null) { - mService.mStackSupervisor.updatePictureInPictureMode(tr, - enterPipBounds, true); - } - - final int windowingMode = c.getWindowingMode(); - if (windowingMode > -1) { - tr.setWindowingMode(windowingMode); - } - final int childWindowingMode = c.getActivityWindowingMode(); - if (childWindowingMode > -1) { - tr.setActivityWindowingMode(childWindowingMode); - } - - return effects; - } - - @Override - public int applyContainerTransaction(WindowContainerTransaction t, ITaskOrganizer organizer) { - enforceStackPermission("applyContainerTransaction()"); - int syncId = -1; - if (t == null) { - throw new IllegalArgumentException( - "Null transaction passed to applyContainerTransaction"); - } - long ident = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - int effects = 0; - - /** - * If organizer is non-null we are looking to synchronize this transaction - * by collecting all the results in to a SurfaceFlinger transaction and - * then delivering that to the given organizers transaction ready callback. - * See {@link BLASTSyncEngine} for the details of the operation. But at - * a high level we create a sync operation with a given ID and an associated - * organizer. Then we notify each WindowContainer in this WindowContainer - * transaction that it is participating in a sync operation with that - * ID. Once everything is notified we tell the BLASTSyncEngine - * "setSyncReady" which means that we have added everything - * to the set. At any point after this, all the WindowContainers - * will eventually finish applying their changes and notify the - * BLASTSyncEngine which will deliver the Transaction to the organizer. - */ - if (organizer != null) { - syncId = startSyncWithOrganizer(organizer); - } - mService.deferWindowLayout(); - try { - ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>(); - Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries = - t.getChanges().entrySet().iterator(); - while (entries.hasNext()) { - final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = - entries.next(); - final WindowContainer wc = WindowContainer.fromBinder(entry.getKey()); - int containerEffect = applyWindowContainerChange(wc, entry.getValue()); - effects |= containerEffect; - - // Lifecycle changes will trigger ensureConfig for everything. - if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0 - && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) { - haveConfigChanges.add(wc); - } - if (syncId >= 0) { - mBLASTSyncEngine.addToSyncSet(syncId, wc); - } - } - // Hierarchy changes - final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps(); - for (int i = 0, n = hops.size(); i < n; ++i) { - final WindowContainerTransaction.HierarchyOp hop = hops.get(i); - final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); - effects |= sanitizeAndApplyHierarchyOp(wc, hop); - } - if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) { - // Already calls ensureActivityConfig - mService.mRootWindowContainer.ensureActivitiesVisible( - null, 0, PRESERVE_WINDOWS); - } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) { - final PooledConsumer f = PooledLambda.obtainConsumer( - ActivityRecord::ensureActivityConfiguration, - PooledLambda.__(ActivityRecord.class), 0, - false /* preserveWindow */); - try { - for (int i = haveConfigChanges.size() - 1; i >= 0; --i) { - final WindowContainer wc = haveConfigChanges.valueAt(i); - final Task task = wc.asTask(); - final TaskTile tile = task != null ? task.asTile() : null; - if (tile != null) { - // Special case for tile. Can't override normal forAllActivities - // because it generates duplicate calls and messes up existing - // code-paths. - tile.forAllTileActivities(f); - } else { - wc.forAllActivities(f); - } - } - } finally { - f.recycle(); - } - } - } finally { - mService.continueWindowLayout(); - if (syncId >= 0) { - setSyncReady(syncId); - } - } - } - } finally { - Binder.restoreCallingIdentity(ident); - } - return syncId; - } - - @Override - public void transactionReady(int id, SurfaceControl.Transaction sc) { - final ITaskOrganizer organizer = mTaskOrganizersByPendingSyncId.get(id); - if (organizer == null) { - Slog.e(TAG, "Got transaction complete for unexpected ID"); - } - try { - organizer.transactionReady(id, sc); - } catch (RemoteException e) { - } - - mTaskOrganizersByPendingSyncId.remove(id); - } - - int startSyncWithOrganizer(ITaskOrganizer organizer) { - int id = mBLASTSyncEngine.startSyncSet(this); - mTaskOrganizersByPendingSyncId.put(id, organizer); - return id; - } - - void setSyncReady(int id) { - mBLASTSyncEngine.setReady(id); - } } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java new file mode 100644 index 000000000000..ebfe1096540e --- /dev/null +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -0,0 +1,347 @@ +/* + * 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.server.wm; + +import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; + +import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG; +import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; +import static com.android.server.wm.WindowContainer.POSITION_TOP; + +import android.app.WindowConfiguration; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.ArraySet; +import android.util.Slog; +import android.view.SurfaceControl; +import android.window.ITaskOrganizerController; +import android.window.IWindowContainerTransactionCallback; +import android.window.IWindowOrganizerController; +import android.window.WindowContainerTransaction; + +import com.android.internal.util.function.pooled.PooledConsumer; +import com.android.internal.util.function.pooled.PooledLambda; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Server side implementation for the interface for organizing windows + * @see android.window.WindowOrganizer + */ +class WindowOrganizerController extends IWindowOrganizerController.Stub + implements BLASTSyncEngine.TransactionReadyListener { + + private static final String TAG = "WindowOrganizerController"; + + /** Flag indicating that an applied transaction may have effected lifecycle */ + private static final int TRANSACT_EFFECTS_CLIENT_CONFIG = 1; + private static final int TRANSACT_EFFECTS_LIFECYCLE = 1 << 1; + + /** + * Masks specifying which configurations task-organizers can control. Incoming transactions + * will be filtered to only include these. + */ + static final int CONTROLLABLE_CONFIGS = ActivityInfo.CONFIG_WINDOW_CONFIGURATION + | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE; + static final int CONTROLLABLE_WINDOW_CONFIGS = WindowConfiguration.WINDOW_CONFIG_BOUNDS + | WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; + + private final ActivityTaskManagerService mService; + private final WindowManagerGlobalLock mGlobalLock; + + private final BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine(); + private final HashMap<Integer, IWindowContainerTransactionCallback> + mTransactionCallbacksByPendingSyncId = new HashMap(); + + final TaskOrganizerController mTaskOrganizerController; + + WindowOrganizerController(ActivityTaskManagerService atm) { + mService = atm; + mGlobalLock = atm.mGlobalLock; + mTaskOrganizerController = new TaskOrganizerController(mService); + } + + @Override + public void applyTransaction(WindowContainerTransaction t) { + applySyncTransaction(t, null /*callback*/); + } + + @Override + public int applySyncTransaction(WindowContainerTransaction t, + IWindowContainerTransactionCallback callback) { + enforceStackPermission("applySyncTransaction()"); + int syncId = -1; + if (t == null) { + throw new IllegalArgumentException( + "Null transaction passed to applySyncTransaction"); + } + long ident = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + int effects = 0; + + /** + * If callback is non-null we are looking to synchronize this transaction by + * collecting all the results in to a SurfaceFlinger transaction and then delivering + * that to the given transaction ready callback. See {@link BLASTSyncEngine} for the + * details of the operation. But at a high level we create a sync operation with a + * given ID and an associated callback. Then we notify each WindowContainer in this + * WindowContainer transaction that it is participating in a sync operation with + * that ID. Once everything is notified we tell the BLASTSyncEngine "setSyncReady" + * which means that we have added everything to the set. At any point after this, + * all the WindowContainers will eventually finish applying their changes and notify + * the BLASTSyncEngine which will deliver the Transaction to the callback. + */ + if (callback != null) { + syncId = startSyncWithOrganizer(callback); + } + mService.deferWindowLayout(); + try { + ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>(); + Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries = + t.getChanges().entrySet().iterator(); + while (entries.hasNext()) { + final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = + entries.next(); + final WindowContainer wc = WindowContainer.fromBinder(entry.getKey()); + int containerEffect = applyWindowContainerChange(wc, entry.getValue()); + effects |= containerEffect; + + // Lifecycle changes will trigger ensureConfig for everything. + if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0 + && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) { + haveConfigChanges.add(wc); + } + if (syncId >= 0) { + mBLASTSyncEngine.addToSyncSet(syncId, wc); + } + } + // Hierarchy changes + final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps(); + for (int i = 0, n = hops.size(); i < n; ++i) { + final WindowContainerTransaction.HierarchyOp hop = hops.get(i); + final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); + effects |= sanitizeAndApplyHierarchyOp(wc, hop); + } + if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) { + // Already calls ensureActivityConfig + mService.mRootWindowContainer.ensureActivitiesVisible( + null, 0, PRESERVE_WINDOWS); + } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) { + final PooledConsumer f = PooledLambda.obtainConsumer( + ActivityRecord::ensureActivityConfiguration, + PooledLambda.__(ActivityRecord.class), 0, + false /* preserveWindow */); + try { + for (int i = haveConfigChanges.size() - 1; i >= 0; --i) { + final WindowContainer wc = haveConfigChanges.valueAt(i); + final Task task = wc.asTask(); + final TaskTile tile = task != null ? task.asTile() : null; + if (tile != null) { + // Special case for tile. Can't override normal forAllActivities + // because it generates duplicate calls and messes up existing + // code-paths. + tile.forAllTileActivities(f); + } else { + wc.forAllActivities(f); + } + } + } finally { + f.recycle(); + } + } + } finally { + mService.continueWindowLayout(); + if (syncId >= 0) { + setSyncReady(syncId); + } + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + return syncId; + } + + private int sanitizeAndApplyChange(WindowContainer container, + WindowContainerTransaction.Change change) { + if (!(container instanceof Task)) { + throw new RuntimeException("Invalid token in task transaction"); + } + final Task task = (Task) container; + // The "client"-facing API should prevent bad changes; however, just in case, sanitize + // masks here. + final int configMask = change.getConfigSetMask() & CONTROLLABLE_CONFIGS; + final int windowMask = change.getWindowSetMask() & CONTROLLABLE_WINDOW_CONFIGS; + int effects = 0; + if (configMask != 0) { + Configuration c = new Configuration(container.getRequestedOverrideConfiguration()); + c.setTo(change.getConfiguration(), configMask, windowMask); + container.onRequestedOverrideConfigurationChanged(c); + // TODO(b/145675353): remove the following once we could apply new bounds to the + // pinned stack together with its children. + resizePinnedStackIfNeeded(container, configMask, windowMask, c); + effects |= TRANSACT_EFFECTS_CLIENT_CONFIG; + } + if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_FOCUSABLE) != 0) { + if (container.setFocusable(change.getFocusable())) { + effects |= TRANSACT_EFFECTS_LIFECYCLE; + } + } + if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) { + if (task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, change.getHidden())) { + effects |= TRANSACT_EFFECTS_LIFECYCLE; + } + } + return effects; + } + + private int sanitizeAndApplyHierarchyOp(WindowContainer container, + WindowContainerTransaction.HierarchyOp hop) { + if (!(container instanceof Task)) { + throw new IllegalArgumentException("Invalid container in hierarchy op"); + } + if (container.getDisplayContent() == null) { + Slog.w(TAG, "Container is no longer attached: " + container); + return 0; + } + if (hop.isReparent()) { + // special case for tiles since they are "virtual" parents + if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) { + ActivityStack as = (ActivityStack) container; + TaskTile newParent = hop.getNewParent() == null ? null + : (TaskTile) WindowContainer.fromBinder(hop.getNewParent()); + if (as.getTile() != newParent) { + if (as.getTile() != null) { + as.getTile().removeChild(as); + } + if (newParent != null) { + if (!as.affectedBySplitScreenResize()) { + return 0; + } + newParent.addChild(as, POSITION_TOP); + } + } + if (hop.getToTop()) { + as.getDisplay().positionStackAtTop(as, false /* includingParents */); + } else { + as.getDisplay().positionStackAtBottom(as); + } + } else if (container instanceof Task) { + throw new RuntimeException("Reparenting leaf Tasks is not supported now."); + } + } else { + // Ugh, of course ActivityStack has its own special reorder logic... + if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) { + ActivityStack as = (ActivityStack) container; + if (hop.getToTop()) { + as.getDisplay().positionStackAtTop(as, false /* includingParents */); + } else { + as.getDisplay().positionStackAtBottom(as); + } + } else { + container.getParent().positionChildAt( + hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM, + container, false /* includingParents */); + } + } + return TRANSACT_EFFECTS_LIFECYCLE; + } + + private int applyWindowContainerChange(WindowContainer wc, + WindowContainerTransaction.Change c) { + int effects = sanitizeAndApplyChange(wc, c); + + final Task tr = wc.asTask(); + + final SurfaceControl.Transaction t = c.getBoundsChangeTransaction(); + if (t != null) { + tr.setMainWindowSizeChangeTransaction(t); + } + + Rect enterPipBounds = c.getEnterPipBounds(); + if (enterPipBounds != null) { + mService.mStackSupervisor.updatePictureInPictureMode(tr, + enterPipBounds, true); + } + + final int windowingMode = c.getWindowingMode(); + if (windowingMode > -1) { + tr.setWindowingMode(windowingMode); + } + final int childWindowingMode = c.getActivityWindowingMode(); + if (childWindowingMode > -1) { + tr.setActivityWindowingMode(childWindowingMode); + } + + return effects; + } + + private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask, + int windowMask, Configuration config) { + if ((container instanceof ActivityStack) + && ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) + && ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) { + final ActivityStack stack = (ActivityStack) container; + if (stack.inPinnedWindowingMode()) { + stack.resize(config.windowConfiguration.getBounds(), + null /* configBounds */, PRESERVE_WINDOWS, true /* deferResume */); + } + } + } + + @Override + public ITaskOrganizerController getTaskOrganizerController() { + enforceStackPermission("getTaskOrganizerController()"); + return mTaskOrganizerController; + } + + int startSyncWithOrganizer(IWindowContainerTransactionCallback callback) { + int id = mBLASTSyncEngine.startSyncSet(this); + mTransactionCallbacksByPendingSyncId.put(id, callback); + return id; + } + + void setSyncReady(int id) { + mBLASTSyncEngine.setReady(id); + } + + @Override + public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) { + final IWindowContainerTransactionCallback callback = + mTransactionCallbacksByPendingSyncId.get(mSyncId); + + try { + callback.transactionReady(mSyncId, mergedTransaction); + } catch (RemoteException e) { + } + + mTransactionCallbacksByPendingSyncId.remove(mSyncId); + } + + private void enforceStackPermission(String func) { + mService.mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, func); + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 873fa0222002..658ba1ba8a4a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -1026,9 +1026,6 @@ public class ActivityStarterTests extends ActivityTestsBase { public void taskVanished(ActivityManager.RunningTaskInfo info) { } @Override - public void transactionReady(int id, SurfaceControl.Transaction t) { - } - @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { if (mInSplit) { return; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index 1624bbc1d472..5359bd33e70f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -231,7 +231,7 @@ public class TaskOrganizerTests extends WindowTestsBase { WindowContainerTransaction t = new WindowContainerTransaction(); Rect newBounds = new Rect(10, 10, 100, 100); t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100)); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertEquals(newBounds, task.getBounds()); } @@ -246,7 +246,7 @@ public class TaskOrganizerTests extends WindowTestsBase { assertEquals(stack.mRemoteToken, info.stackToken); Rect newBounds = new Rect(10, 10, 100, 100); t.setBounds(info.stackToken, new Rect(10, 10, 100, 100)); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertEquals(newBounds, stack.getBounds()); } @@ -257,7 +257,7 @@ public class TaskOrganizerTests extends WindowTestsBase { final WindowContainerTransaction t = new WindowContainerTransaction(); t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode()); } @@ -270,7 +270,7 @@ public class TaskOrganizerTests extends WindowTestsBase { t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED); t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode()); assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode()); @@ -285,10 +285,10 @@ public class TaskOrganizerTests extends WindowTestsBase { WindowContainerTransaction t = new WindowContainerTransaction(); assertTrue(task.isFocusable()); t.setFocusable(stack.mRemoteToken, false); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertFalse(task.isFocusable()); t.setFocusable(stack.mRemoteToken, true); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertTrue(task.isFocusable()); } @@ -300,10 +300,10 @@ public class TaskOrganizerTests extends WindowTestsBase { WindowContainerTransaction t = new WindowContainerTransaction(); assertTrue(stack.shouldBeVisible(null)); t.setHidden(stack.mRemoteToken, true); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertFalse(stack.shouldBeVisible(null)); t.setHidden(stack.mRemoteToken, false); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertTrue(stack.shouldBeVisible(null)); } @@ -315,19 +315,19 @@ public class TaskOrganizerTests extends WindowTestsBase { final Task task = stack.getTopMostTask(); WindowContainerTransaction t = new WindowContainerTransaction(); t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100)); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); final int origScreenWDp = task.getConfiguration().screenHeightDp; final int origScreenHDp = task.getConfiguration().screenHeightDp; t = new WindowContainerTransaction(); // verify that setting config overrides on parent restricts children. t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp); t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200)); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp); t = new WindowContainerTransaction(); t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED, Configuration.SCREEN_HEIGHT_DP_UNDEFINED); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp); } @@ -402,9 +402,6 @@ public class TaskOrganizerTests extends WindowTestsBase { public void taskVanished(RunningTaskInfo container) { } @Override - public void transactionReady(int id, SurfaceControl.Transaction t) { } - - @Override public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException { lastReportedTiles.add(info); called[0] = true; @@ -456,9 +453,6 @@ public class TaskOrganizerTests extends WindowTestsBase { public void taskVanished(RunningTaskInfo container) { } @Override - public void transactionReady(int id, SurfaceControl.Transaction t) { } - - @Override public void onTaskInfoChanged(RunningTaskInfo info) { lastReportedTiles.put(info.token.asBinder(), info); } @@ -487,8 +481,7 @@ public class TaskOrganizerTests extends WindowTestsBase { WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */); wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct, - null /* organizer */); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct); assertFalse(lastReportedTiles.isEmpty()); assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(info1.token.asBinder()).topActivityType); @@ -498,8 +491,7 @@ public class TaskOrganizerTests extends WindowTestsBase { lastReportedTiles.clear(); wct = new WindowContainerTransaction(); wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct, - null /* organizer */); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct); assertFalse(lastReportedTiles.isEmpty()); // Standard should still be on top of tile 1, so no change there assertFalse(lastReportedTiles.containsKey(info1.token.asBinder())); @@ -524,8 +516,7 @@ public class TaskOrganizerTests extends WindowTestsBase { lastReportedTiles.clear(); wct = new WindowContainerTransaction(); wct.reorder(stack2.mRemoteToken, true /* onTop */); - mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct, - null /* organizer */); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct); // Home should now be on top. No change occurs in second tile, so not reported assertEquals(1, lastReportedTiles.size()); assertEquals(ACTIVITY_TYPE_HOME, @@ -683,9 +674,6 @@ public class TaskOrganizerTests extends WindowTestsBase { public void taskVanished(RunningTaskInfo info) { } @Override - public void transactionReady(int id, SurfaceControl.Transaction t) { - } - @Override public void onTaskInfoChanged(RunningTaskInfo info) { } }; diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java index cb75c8ba5873..f186ed3b75cf 100644 --- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java @@ -17,9 +17,9 @@ package com.android.test.taskembed; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static android.window.WindowOrganizer.TaskOrganizer; import android.app.ActivityManager; -import android.app.ActivityTaskManager; import android.app.Activity; import android.app.ActivityOptions; import android.content.Context; @@ -27,6 +27,8 @@ import android.content.Intent; import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; import android.view.Gravity; import android.view.MotionEvent; import android.view.SurfaceControl; @@ -34,8 +36,10 @@ import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup; import android.window.ITaskOrganizer; +import android.window.IWindowContainerTransactionCallback; import android.window.WindowContainerTransaction; import android.widget.LinearLayout; +import android.window.WindowOrganizer; public class TaskOrganizerMultiWindowTest extends Activity { class SplitLayout extends LinearLayout implements View.OnTouchListener { @@ -112,8 +116,7 @@ public class TaskOrganizerMultiWindowTest extends Activity { final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setBounds(mWc, new Rect(0, 0, width, height)); try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, - mOrganizer); + WindowOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback); } catch (Exception e) { // Oh well } @@ -127,6 +130,25 @@ public class TaskOrganizerMultiWindowTest extends Activity { class Organizer extends ITaskOrganizer.Stub { private int receivedTransactions = 0; SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction(); + IWindowContainerTransactionCallback mTransactionCallback = + new IWindowContainerTransactionCallback() { + @Override + public void transactionReady(int id, SurfaceControl.Transaction t) + throws RemoteException { + mergedTransaction.merge(t); + receivedTransactions++; + if (receivedTransactions == 2) { + mergedTransaction.apply(); + receivedTransactions = 0; + } + } + + @Override + public IBinder asBinder() { + return null; + } + }; + @Override public void taskAppeared(ActivityManager.RunningTaskInfo ti) { if (!gotFirstTask) { @@ -138,14 +160,6 @@ public class TaskOrganizerMultiWindowTest extends Activity { } public void taskVanished(ActivityManager.RunningTaskInfo ti) { } - public void transactionReady(int id, SurfaceControl.Transaction t) { - mergedTransaction.merge(t); - receivedTransactions++; - if (receivedTransactions == 2) { - mergedTransaction.apply(); - receivedTransactions = 0; - } - } @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { } @@ -158,9 +172,7 @@ public class TaskOrganizerMultiWindowTest extends Activity { super.onCreate(savedInstanceState); try { - ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(mOrganizer, - WINDOWING_MODE_MULTI_WINDOW); - + TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_MULTI_WINDOW); } catch (Exception e) { } diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java index 177841d97ff5..a2f40dc0fd6f 100644 --- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java @@ -17,19 +17,19 @@ package com.android.test.taskembed; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.window.WindowOrganizer.TaskOrganizer; import android.app.ActivityManager; -import android.app.ActivityTaskManager; import android.app.Service; import android.content.Intent; import android.graphics.Rect; import android.os.IBinder; -import android.view.SurfaceControl; import android.view.ViewGroup; import android.window.ITaskOrganizer; import android.window.WindowContainerTransaction; import android.view.WindowManager; import android.widget.FrameLayout; +import android.window.WindowOrganizer; public class TaskOrganizerPipTest extends Service { static final int PIP_WIDTH = 640; @@ -44,14 +44,12 @@ public class TaskOrganizerPipTest extends Service { final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.scheduleFinishEnterPip(ti.token, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT)); try { - ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, null); + WindowOrganizer.applyTransaction(wct); } catch (Exception e) { } } public void taskVanished(ActivityManager.RunningTaskInfo ti) { } - public void transactionReady(int id, SurfaceControl.Transaction t) { - } public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { } } @@ -68,9 +66,7 @@ public class TaskOrganizerPipTest extends Service { super.onCreate(); try { - ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(mOrganizer, - WINDOWING_MODE_PINNED); - + TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_PINNED); } catch (Exception e) { } |