Merge "Introduce WindowOrganizer" into rvc-dev
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index c9673f5..1b941de 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -30,7 +30,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Singleton;
-import android.window.ITaskOrganizerController;
import java.util.List;
@@ -159,24 +158,6 @@
}
};
- /** @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 ab5c678..03717ec 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -29,7 +29,6 @@
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.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 @@
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 b2da239..0a04462 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 @@
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 e8af8e1..a8b6aae 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -36,20 +36,6 @@
*/
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 0000000..0579932
--- /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 0000000..4b47924
--- /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 0000000..b8969c1
--- /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 e64a919..c287055 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.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 @@
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 @@
@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 @@
}
@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 @@
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 a0dff3f..e89ce2e 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 @@
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.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 @@
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 050acd5..2dcf1f8 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 @@
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.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 @@
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 3d52812..01498f9 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.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.SurfaceSession;
import android.view.View;
import android.window.WindowContainerTransaction;
+import android.window.WindowOrganizer;
import androidx.annotation.Nullable;
@@ -177,8 +178,7 @@
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 @@
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 @@
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 @@
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 f82936a..8bbb548 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.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 @@
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 @@
}
@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 0e391ec..8724e49 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_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.window.IWindowContainer;
import android.window.WindowContainerTransaction;
import android.view.WindowManagerGlobal;
+import android.window.WindowOrganizer;
import com.android.internal.annotations.GuardedBy;
@@ -111,8 +113,7 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
// 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 @@
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 1844395..f7278e7 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.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 @@
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 @@
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 @@
}
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, tile.mRemoteToken, toTop);
- mTaskOrganizerController.applyContainerTransaction(wct, null);
+ mWindowOrganizerController.applyTransaction(wct);
}
/**
@@ -4311,7 +4312,7 @@
}
}
wct.setBounds(secondary.mRemoteToken, otherRect);
- mTaskOrganizerController.applyContainerTransaction(wct, null /* organizer */);
+ mWindowOrganizerController.applyTransaction(wct);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -4332,10 +4333,10 @@
}
@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 776a986..60b817c 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 @@
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 9bf4d63..fc58ee7 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_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 @@
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 @@
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 0000000..ebfe109
--- /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 873fa02..658ba1b 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 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 1624bbc..5359bd3 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 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 @@
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 @@
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 @@
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 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 cb75c8b..f186ed3 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.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.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 @@
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 @@
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 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 @@
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 177841d..a2f40dc 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 @@
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 @@
super.onCreate();
try {
- ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(mOrganizer,
- WINDOWING_MODE_PINNED);
-
+ TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_PINNED);
} catch (Exception e) {
}