summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
author Garfield Tan <xutan@google.com> 2022-07-08 13:29:03 -0700
committer Garfield Tan <xutan@google.com> 2022-07-27 09:48:50 -0700
commit1e37f5519ba2ff66525fd7d33c4313ffbcf0c9e2 (patch)
treeac4f75a799ed67ffdc58c68389d92a3c883086f6 /libs
parent5a409f7a775f0c6ce9e06b3c958ba670a9ed0423 (diff)
Add FreeformTaskTransitionHandler
This change ties the window decoration lifecycle to shell transitions if it's enabled, so that we can leverage the new transition handler to hand over window decorations. This change exposes the transfers of management of tasks to task listeners to implement maximizing. Eventually I want to use it to implement the passover of window decorations across listeners. This change lets freeform code handle maximizing transitions because there isn't anything special to do for fullscreen tasks with window decorations so we can keep FullscreenTaskListener simple. Currently all animations related to freeform tasks are jumpcuts because there isn't any spec defined. Bug: 205580520 Test: Open, close, maximize freeform tasks with the shell transition and the caption in shell enabled. Test: atest WindowDecorationTests Change-Id: Ie7bb92e0b5946b006fa685f4438815627c72dffe
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java56
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java178
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java234
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java48
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java41
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java20
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java30
14 files changed, 630 insertions, 100 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 5dd51499ef19..a168cb22f6ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -29,8 +29,6 @@ import com.android.internal.logging.UiEventLogger;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
-import com.android.wm.shell.sysui.ShellCommandHandler;
-import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.TaskViewFactoryController;
@@ -59,7 +57,7 @@ import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
import com.android.wm.shell.draganddrop.DragAndDropController;
-import com.android.wm.shell.freeform.FreeformTaskListener;
+import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
@@ -78,7 +76,9 @@ import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
+import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
+import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.sysui.ShellInterface;
import com.android.wm.shell.transition.ShellTransitions;
import com.android.wm.shell.transition.Transitions;
@@ -339,15 +339,15 @@ public abstract class WMShellBaseModule {
// Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
@BindsOptionalOf
@DynamicOverride
- abstract FreeformTaskListener<?> optionalFreeformTaskListener();
+ abstract FreeformComponents optionalFreeformComponents();
@WMSingleton
@Provides
- static Optional<FreeformTaskListener<?>> provideFreeformTaskListener(
- @DynamicOverride Optional<FreeformTaskListener<?>> freeformTaskListener,
+ static Optional<FreeformComponents> provideFreeformTaskListener(
+ @DynamicOverride Optional<FreeformComponents> freeformComponents,
Context context) {
- if (FreeformTaskListener.isFreeformEnabled(context)) {
- return freeformTaskListener;
+ if (FreeformComponents.isFreeformEnabled(context)) {
+ return freeformComponents;
}
return Optional.empty();
}
@@ -636,7 +636,7 @@ public abstract class WMShellBaseModule {
FullscreenTaskListener fullscreenTaskListener,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
- Optional<FreeformTaskListener<?>> freeformTaskListener,
+ Optional<FreeformComponents> freeformComponents,
Optional<RecentTasksController> recentTasksOptional,
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
Transitions transitions,
@@ -655,7 +655,7 @@ public abstract class WMShellBaseModule {
fullscreenTaskListener,
unfoldAnimationController,
unfoldTransitionHandler,
- freeformTaskListener,
+ freeformComponents,
recentTasksOptional,
activityEmbeddingOptional,
transitions,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 0dc293b0265f..588a1aa57a3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -49,7 +49,9 @@ import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.freeform.FreeformTaskListener;
+import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
@@ -194,10 +196,27 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
@DynamicOverride
+ static FreeformComponents provideFreeformComponents(
+ FreeformTaskListener<?> taskListener,
+ FreeformTaskTransitionHandler transitionHandler) {
+ return new FreeformComponents(taskListener, Optional.of(transitionHandler));
+ }
+
+ @WMSingleton
+ @Provides
static FreeformTaskListener<?> provideFreeformTaskListener(
+ WindowDecorViewModel<?> windowDecorViewModel) {
+ return new FreeformTaskListener<>(windowDecorViewModel);
+ }
+
+ @WMSingleton
+ @Provides
+ static FreeformTaskTransitionHandler provideTaskTransitionHandler(
+ Transitions transitions,
WindowDecorViewModel<?> windowDecorViewModel,
- SyncTransactionQueue syncQueue) {
- return new FreeformTaskListener<>(windowDecorViewModel, syncQueue);
+ FreeformTaskListener<?> freeformTaskListener) {
+ return new FreeformTaskTransitionHandler(transitions, windowDecorViewModel,
+ freeformTaskListener);
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java
new file mode 100644
index 000000000000..41e1b1de2546
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformComponents.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.transition.Transitions;
+
+import java.util.Optional;
+
+/**
+ * Class that holds freeform related classes. It serves as the single injection point of
+ * all freeform classes to avoid leaking implementation details to the base Dagger module.
+ */
+public class FreeformComponents {
+ public final ShellTaskOrganizer.TaskListener mTaskListener;
+ public final Optional<Transitions.TransitionHandler> mTaskTransitionHandler;
+
+ /**
+ * Creates an instance with the given components.
+ */
+ public FreeformComponents(
+ ShellTaskOrganizer.TaskListener taskListener,
+ Optional<Transitions.TransitionHandler> taskTransitionHandler) {
+ mTaskListener = taskListener;
+ mTaskTransitionHandler = taskTransitionHandler;
+ }
+
+ /**
+ * Returns if this device supports freeform.
+ */
+ public static boolean isFreeformEnabled(Context context) {
+ return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
+ || Settings.Global.getInt(context.getContentResolver(),
+ DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 692e6acb540c..ba093a5fcc05 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -16,20 +16,18 @@
package com.android.wm.shell.freeform;
-import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
-
import android.app.ActivityManager.RunningTaskInfo;
-import android.content.Context;
-import android.provider.Settings;
-import android.util.Slog;
+import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+
+import androidx.annotation.Nullable;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import java.io.PrintWriter;
@@ -45,9 +43,9 @@ public class FreeformTaskListener<T extends AutoCloseable>
private static final String TAG = "FreeformTaskListener";
private final WindowDecorViewModel<T> mWindowDecorationViewModel;
- private final SyncTransactionQueue mSyncQueue;
private final SparseArray<State<T>> mTasks = new SparseArray<>();
+ private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
private static class State<T extends AutoCloseable> {
RunningTaskInfo mTaskInfo;
@@ -55,57 +53,78 @@ public class FreeformTaskListener<T extends AutoCloseable>
T mWindowDecoration;
}
- public FreeformTaskListener(
- WindowDecorViewModel<T> windowDecorationViewModel,
- SyncTransactionQueue syncQueue) {
+ public FreeformTaskListener(WindowDecorViewModel<T> windowDecorationViewModel) {
mWindowDecorationViewModel = windowDecorationViewModel;
- mSyncQueue = syncQueue;
}
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (mTasks.get(taskInfo.taskId) != null) {
- throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
- }
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
taskInfo.taskId);
- final State<T> state = new State<>();
+ final State<T> state = createOrUpdateTaskState(taskInfo, leash);
+ if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ state.mWindowDecoration =
+ mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
+ t.apply();
+ }
+ }
+
+ private State<T> createOrUpdateTaskState(RunningTaskInfo taskInfo, SurfaceControl leash) {
+ State<T> state = mTasks.get(taskInfo.taskId);
+ if (state != null) {
+ updateTaskInfo(taskInfo);
+ return state;
+ }
+
+ state = new State<>();
state.mTaskInfo = taskInfo;
state.mLeash = leash;
- state.mWindowDecoration =
- mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash);
mTasks.put(taskInfo.taskId, state);
+
+ return state;
}
@Override
public void onTaskVanished(RunningTaskInfo taskInfo) {
- State<T> state = mTasks.get(taskInfo.taskId);
+ final State<T> state = mTasks.get(taskInfo.taskId);
if (state == null) {
- Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ // This is possible if the transition happens before this method.
return;
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
taskInfo.taskId);
mTasks.remove(taskInfo.taskId);
- try {
- state.mWindowDecoration.close();
- } catch (Exception e) {
- Slog.e(TAG, "Failed to release window decoration.", e);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ // Save window decorations of closing tasks so that we can hand them over to the
+ // transition system if this method happens before the transition. In case where the
+ // transition didn't happen, it'd be cleared when the next transition finished.
+ if (state.mWindowDecoration != null) {
+ mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration);
+ }
+ return;
}
+ releaseWindowDecor(state.mWindowDecoration);
}
@Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
- State<T> state = mTasks.get(taskInfo.taskId);
- if (state == null) {
- throw new RuntimeException(
- "Task info changed before appearing: #" + taskInfo.taskId);
- }
+ final State<T> state = updateTaskInfo(taskInfo);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
taskInfo.taskId);
+ if (state.mWindowDecoration != null) {
+ mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
+ }
+ }
+
+ private State<T> updateTaskInfo(RunningTaskInfo taskInfo) {
+ final State<T> state = mTasks.get(taskInfo.taskId);
+ if (state == null) {
+ throw new RuntimeException("Task info changed before appearing: #" + taskInfo.taskId);
+ }
state.mTaskInfo = taskInfo;
- mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
+ return state;
}
@Override
@@ -126,6 +145,93 @@ public class FreeformTaskListener<T extends AutoCloseable>
return mTasks.get(taskId).mLeash;
}
+ /**
+ * Creates a window decoration for a transition.
+ *
+ * @param change the change of this task transition that needs to have the task layer as the
+ * leash
+ * @return {@code true} if it adopts the window decoration; {@code false} otherwise
+ */
+ void createWindowDecoration(
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
+ state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
+ state.mTaskInfo, state.mLeash, startT, finishT);
+ }
+
+ /**
+ * Gives out the ownership of the task's window decoration. The given task is leaving (of has
+ * left) this task listener. This is the transition system asking for the ownership.
+ *
+ * @param taskInfo the maximizing task
+ * @return the window decor of the maximizing task if any
+ */
+ T giveWindowDecoration(
+ RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ T windowDecor = mWindowDecorOfVanishedTasks.get(taskInfo.taskId);
+ mWindowDecorOfVanishedTasks.remove(taskInfo.taskId);
+ final State<T> state = mTasks.get(taskInfo.taskId);
+ if (state != null) {
+ windowDecor = windowDecor == null ? state.mWindowDecoration : windowDecor;
+ state.mWindowDecoration = null;
+ }
+ mWindowDecorationViewModel.setupWindowDecorationForTransition(
+ taskInfo, startT, finishT, windowDecor);
+ return windowDecor;
+ }
+
+ /**
+ * Adopt the incoming window decoration and lets the window decoration prepare for a transition.
+ *
+ * @param change the change of this task transition that needs to have the task layer as the
+ * leash
+ * @param startT the start transaction of this transition
+ * @param finishT the finish transaction of this transition
+ * @param windowDecor the window decoration to adopt
+ * @return {@code true} if it adopts the window decoration; {@code false} otherwise
+ */
+ boolean adoptWindowDecoration(
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT,
+ @Nullable AutoCloseable windowDecor) {
+ final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
+ state.mWindowDecoration = mWindowDecorationViewModel.adoptWindowDecoration(windowDecor);
+ if (state.mWindowDecoration != null) {
+ mWindowDecorationViewModel.setupWindowDecorationForTransition(
+ state.mTaskInfo, startT, finishT, state.mWindowDecoration);
+ return true;
+ } else {
+ state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
+ state.mTaskInfo, state.mLeash, startT, finishT);
+ return false;
+ }
+ }
+
+ void onTaskTransitionFinished() {
+ if (mWindowDecorOfVanishedTasks.size() == 0) {
+ return;
+ }
+ Log.w(TAG, "Clearing window decors of vanished tasks. There could be visual defects "
+ + "if any of them is used later in transitions.");
+ for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
+ releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
+ }
+ mWindowDecorOfVanishedTasks.clear();
+ }
+
+ private void releaseWindowDecor(T windowDecor) {
+ try {
+ windowDecor.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to release window decoration.", e);
+ }
+ }
+
@Override
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
@@ -137,16 +243,4 @@ public class FreeformTaskListener<T extends AutoCloseable>
public String toString() {
return TAG;
}
-
- /**
- * Checks if freeform support is enabled in system.
- *
- * @param context context used to check settings and package manager.
- * @return {@code true} if freeform is enabled, {@code false} if not.
- */
- public static boolean isFreeformEnabled(Context context) {
- return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
- || Settings.Global.getInt(context.getContentResolver(),
- DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
new file mode 100644
index 000000000000..8731eb604cbc
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.windowdecor.WindowDecorViewModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The {@link Transitions.TransitionHandler} that handles freeform task launches, closes,
+ * maximizing and restoring transitions. It also reports transitions so that window decorations can
+ * be a part of transitions.
+ */
+public class FreeformTaskTransitionHandler
+ implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
+ private static final String TAG = "FreeformTH";
+
+ private final Transitions mTransitions;
+ private final FreeformTaskListener<?> mFreeformTaskListener;
+
+ private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
+
+ public FreeformTaskTransitionHandler(
+ Transitions transitions,
+ WindowDecorViewModel<?> windowDecorViewModel,
+ FreeformTaskListener<?> freeformTaskListener) {
+ mTransitions = transitions;
+ mFreeformTaskListener = freeformTaskListener;
+
+ windowDecorViewModel.setFreeformTaskTransitionStarter(this);
+ }
+
+ @Override
+ public void startWindowingModeTransition(
+ int targetWindowingMode, WindowContainerTransaction wct) {
+ final int type;
+ switch (targetWindowingMode) {
+ case WINDOWING_MODE_FULLSCREEN:
+ type = Transitions.TRANSIT_MAXIMIZE;
+ break;
+ case WINDOWING_MODE_FREEFORM:
+ type = Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE;
+ break;
+ default:
+ throw new IllegalArgumentException("Unexpected target windowing mode "
+ + WindowConfiguration.windowingModeToString(targetWindowingMode));
+ }
+ final IBinder token = mTransitions.startTransition(type, wct, this);
+ mPendingTransitionTokens.add(token);
+ }
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startT,
+ @NonNull SurfaceControl.Transaction finishT,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ boolean transitionHandled = false;
+ final ArrayList<AutoCloseable> windowDecorsInCloseTransitions = new ArrayList<>();
+ for (TransitionInfo.Change change : info.getChanges()) {
+ if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
+ continue;
+ }
+
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (taskInfo == null || taskInfo.taskId == -1) {
+ continue;
+ }
+
+ switch (change.getMode()) {
+ case WindowManager.TRANSIT_OPEN:
+ transitionHandled |= startOpenTransition(change, startT, finishT);
+ break;
+ case WindowManager.TRANSIT_CLOSE:
+ transitionHandled |= startCloseTransition(
+ change, windowDecorsInCloseTransitions, startT, finishT);
+ break;
+ case WindowManager.TRANSIT_CHANGE:
+ transitionHandled |= startChangeTransition(
+ transition, info.getType(), change, startT, finishT);
+ break;
+ case WindowManager.TRANSIT_TO_BACK:
+ case WindowManager.TRANSIT_TO_FRONT:
+ transitionHandled = true;
+ break;
+ }
+ }
+
+ mPendingTransitionTokens.remove(transition);
+
+ if (!transitionHandled) {
+ return false;
+ }
+
+ startT.apply();
+ mTransitions.getMainExecutor().execute(
+ () -> finishTransition(windowDecorsInCloseTransitions, finishCallback));
+ return true;
+ }
+
+ private boolean startOpenTransition(
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+ return false;
+ }
+ mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
+ return true;
+ }
+
+ private boolean startCloseTransition(
+ TransitionInfo.Change change,
+ ArrayList<AutoCloseable> windowDecors,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+ return false;
+ }
+ final AutoCloseable windowDecor =
+ mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(), startT, finishT);
+ if (windowDecor != null) {
+ windowDecors.add(windowDecor);
+ }
+
+ return true;
+ }
+
+ private boolean startChangeTransition(
+ IBinder transition,
+ int type,
+ TransitionInfo.Change change,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ AutoCloseable windowDecor = null;
+
+ if (!mPendingTransitionTokens.contains(transition)) {
+ return false;
+ }
+
+ boolean handled = false;
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (type == Transitions.TRANSIT_MAXIMIZE
+ && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ handled = true;
+ windowDecor = mFreeformTaskListener.giveWindowDecoration(
+ change.getTaskInfo(), startT, finishT);
+ // TODO(b/235638450): Let fullscreen task listener adopt the window decor.
+ }
+
+ if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE
+ && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ handled = true;
+ // TODO(b/235638450): Let fullscreen task listener transfer the window decor.
+ mFreeformTaskListener.adoptWindowDecoration(change, startT, finishT, windowDecor);
+ }
+
+ releaseWindowDecor(windowDecor);
+
+ return handled;
+ }
+
+ private void finishTransition(
+ ArrayList<AutoCloseable> windowDecorsInCloseTransitions,
+ Transitions.TransitionFinishCallback finishCallback) {
+ for (AutoCloseable windowDecor : windowDecorsInCloseTransitions) {
+ releaseWindowDecor(windowDecor);
+ }
+ mFreeformTaskListener.onTaskTransitionFinished();
+ // TODO(b/235638450): Dispatch it to fullscreen task listener.
+ finishCallback.onTransitionFinished(null, null);
+ }
+
+ private void releaseWindowDecor(AutoCloseable windowDecor) {
+ if (windowDecor == null) {
+ return;
+ }
+ try {
+ windowDecor.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to release window decoration.", e);
+ }
+ }
+
+ @Nullable
+ @Override
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ final ActivityManager.RunningTaskInfo taskInfo = request.getTriggerTask();
+ if (taskInfo == null || taskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+ return null;
+ }
+ switch (request.getType()) {
+ case WindowManager.TRANSIT_OPEN:
+ case WindowManager.TRANSIT_CLOSE:
+ case WindowManager.TRANSIT_TO_FRONT:
+ case WindowManager.TRANSIT_TO_BACK:
+ return new WindowContainerTransaction();
+ default:
+ return null;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
new file mode 100644
index 000000000000..25eaa0e05a09
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import android.window.WindowContainerTransaction;
+
+/**
+ * The interface around {@link FreeformTaskTransitionHandler} for task listeners to start freeform
+ * task transitions.
+ */
+public interface FreeformTaskTransitionStarter {
+
+ /**
+ * Starts a windowing mode transition.
+ *
+ * @param targetWindowingMode the target windowing mode
+ * @param wct the {@link WindowContainerTransaction} that changes the windowing mode
+ */
+ void startWindowingModeTransition(int targetWindowingMode, WindowContainerTransaction wct);
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
index 2619b37b67d8..dd7fab7c5f46 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
@@ -34,7 +34,7 @@ import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.draganddrop.DragAndDropController;
-import com.android.wm.shell.freeform.FreeformTaskListener;
+import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.pip.phone.PipTouchHandler;
@@ -68,7 +68,7 @@ public class ShellInit {
private final FullscreenTaskListener mFullscreenTaskListener;
private final Optional<UnfoldAnimationController> mUnfoldController;
private final Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
- private final Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional;
+ private final Optional<FreeformComponents> mFreeformComponentsOptional;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
private final StartingWindowController mStartingWindow;
@@ -93,7 +93,7 @@ public class ShellInit {
FullscreenTaskListener fullscreenTaskListener,
Optional<UnfoldAnimationController> unfoldAnimationController,
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
- Optional<FreeformTaskListener<?>> freeformTaskListenerOptional,
+ Optional<FreeformComponents> freeformComponentsOptional,
Optional<RecentTasksController> recentTasks,
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
Transitions transitions,
@@ -111,7 +111,7 @@ public class ShellInit {
mPipTouchHandlerOptional = pipTouchHandlerOptional;
mUnfoldController = unfoldAnimationController;
mUnfoldTransitionHandler = unfoldTransitionHandler;
- mFreeformTaskListenerOptional = freeformTaskListenerOptional;
+ mFreeformComponentsOptional = freeformComponentsOptional;
mRecentTasks = recentTasks;
mActivityEmbeddingOptional = activityEmbeddingOptional;
mTransitions = transitions;
@@ -143,6 +143,8 @@ public class ShellInit {
mTransitions.register(mShellTaskOrganizer);
mActivityEmbeddingOptional.ifPresent(ActivityEmbeddingController::init);
mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init);
+ mFreeformComponentsOptional.flatMap(f -> f.mTaskTransitionHandler)
+ .ifPresent(mTransitions::addHandler);
if (mSplitScreenOptional.isPresent() && mPipTouchHandlerOptional.isPresent()) {
final DefaultMixedHandler mixedHandler = new DefaultMixedHandler(mTransitions,
mPipTouchHandlerOptional.get().getTransitionHandler(),
@@ -158,9 +160,9 @@ public class ShellInit {
mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
// Initialize optional freeform
- mFreeformTaskListenerOptional.ifPresent(f ->
+ mFreeformComponentsOptional.ifPresent(f ->
mShellTaskOrganizer.addListenerForType(
- f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
+ f.mTaskListener, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
mUnfoldController.ifPresent(UnfoldAnimationController::init);
mRecentTasks.ifPresent(RecentTasksController::init);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index fa22c7ca94d2..8e36154d10e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -98,6 +98,12 @@ public class Transitions implements RemoteCallable<Transitions> {
/** Transition type for dismissing split-screen. */
public static final int TRANSIT_SPLIT_DISMISS = TRANSIT_FIRST_CUSTOM + 7;
+ /** Transition type for freeform to maximize transition. */
+ public static final int TRANSIT_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 8;
+
+ /** Transition type for maximize to freeform transition. */
+ public static final int TRANSIT_RESTORE_FROM_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 9;
+
private final WindowOrganizer mOrganizer;
private final Context mContext;
private final ShellExecutor mMainExecutor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index fe3724b4ec1b..08d6c50f94b4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -36,6 +36,8 @@ import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.transition.Transitions;
/**
* View model for the window decoration with a caption and shadows. Works with
@@ -50,6 +52,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
private final DisplayController mDisplayController;
private final SyncTransactionQueue mSyncQueue;
+ private FreeformTaskTransitionStarter mTransitionStarter;
+
public CaptionWindowDecorViewModel(
Context context,
Handler mainHandler,
@@ -67,8 +71,16 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
}
@Override
+ public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) {
+ mTransitionStarter = transitionStarter;
+ }
+
+ @Override
public CaptionWindowDecoration createWindowDecoration(
- ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface) {
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
mContext,
mDisplayController,
@@ -83,18 +95,39 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
new CaptionTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragResizeCallback(taskPositioner);
- onTaskInfoChanged(taskInfo, windowDecoration);
+ setupWindowDecorationForTransition(taskInfo, startT, finishT, windowDecoration);
+ setupCaptionColor(taskInfo, windowDecoration);
return windowDecoration;
}
@Override
+ public CaptionWindowDecoration adoptWindowDecoration(AutoCloseable windowDecor) {
+ return (windowDecor instanceof CaptionWindowDecoration)
+ ? (CaptionWindowDecoration) windowDecor
+ : null;
+ }
+
+ @Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
decoration.relayout(taskInfo);
+ setupCaptionColor(taskInfo, decoration);
+ }
+
+ private void setupCaptionColor(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
int statusBarColor = taskInfo.taskDescription.getStatusBarColor();
decoration.setCaptionColor(statusBarColor);
}
+ @Override
+ public void setupWindowDecorationForTransition(
+ RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT,
+ CaptionWindowDecoration decoration) {
+ decoration.relayout(taskInfo, startT, finishT);
+ }
+
private class CaptionTouchEventListener implements
View.OnClickListener, View.OnTouchListener {
@@ -105,7 +138,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
private int mDragPointerId = -1;
private CaptionTouchEventListener(
- RunningTaskInfo taskInfo, DragResizeCallback dragResizeCallback) {
+ RunningTaskInfo taskInfo,
+ DragResizeCallback dragResizeCallback) {
mTaskId = taskInfo.taskId;
mTaskToken = taskInfo.token;
mDragResizeCallback = dragResizeCallback;
@@ -113,7 +147,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
@Override
public void onClick(View v) {
- int id = v.getId();
+ final int id = v.getId();
if (id == R.id.close_window) {
mActivityTaskManager.removeTask(mTaskId);
} else if (id == R.id.maximize_window) {
@@ -129,7 +163,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) {
wct.setBounds(mTaskToken, null);
}
- mSyncQueue.queue(wct);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mTransitionStarter.startWindowingModeTransition(targetWindowingMode, wct);
+ } else {
+ mSyncQueue.queue(wct);
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 2df71041595d..dc212fc2ab4d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -101,6 +101,16 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ relayout(taskInfo, t, t);
+ mSyncQueue.runInSync(transaction -> {
+ transaction.merge(t);
+ t.close();
+ });
+ }
+
+ void relayout(ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
final int shadowRadiusDp = taskInfo.isFocused
? DECOR_SHADOW_FOCUSED_THICKNESS_IN_DIP : DECOR_SHADOW_UNFOCUSED_THICKNESS_IN_DIP;
final boolean isFreeform = mTaskInfo.configuration.windowConfiguration.getWindowingMode()
@@ -110,18 +120,12 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
WindowDecorLinearLayout oldRootView = mResult.mRootView;
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
final WindowContainerTransaction wct = new WindowContainerTransaction();
relayout(taskInfo, R.layout.caption_window_decoration, oldRootView,
- DECOR_CAPTION_HEIGHT_IN_DIP, outset, shadowRadiusDp, t, wct, mResult);
+ DECOR_CAPTION_HEIGHT_IN_DIP, outset, shadowRadiusDp, startT, finishT, wct, mResult);
taskInfo = null; // Clear it just in case we use it accidentally
- mSyncQueue.runInSync(transaction -> {
- transaction.merge(t);
- t.close();
-
- mTaskOrganizer.applyTransaction(wct);
- });
+ mTaskOrganizer.applyTransaction(wct);
if (mResult.mRootView == null) {
// This means something blocks the window decor from showing, e.g. the task is hidden.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
index 6f9ceff722ac..c234949572bf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
@@ -19,6 +19,10 @@ package com.android.wm.shell.windowdecor;
import android.app.ActivityManager;
import android.view.SurfaceControl;
+import androidx.annotation.Nullable;
+
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+
/**
* The interface used by some {@link com.android.wm.shell.ShellTaskOrganizer.TaskListener} to help
* customize {@link WindowDecoration}. Its implementations are responsible to interpret user's
@@ -30,13 +34,34 @@ import android.view.SurfaceControl;
public interface WindowDecorViewModel<T extends AutoCloseable> {
/**
+ * Sets the transition starter that starts freeform task transitions.
+ *
+ * @param transitionStarter the transition starter that starts freeform task transitions
+ */
+ void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter);
+
+ /**
* Creates a window decoration for the given task.
*
* @param taskInfo the initial task info of the task
* @param taskSurface the surface of the task
+ * @param startT the start transaction to be applied before the transition
+ * @param finishT the finish transaction to restore states after the transition
* @return the window decoration object
*/
- T createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface);
+ T createWindowDecoration(
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT);
+
+ /**
+ * Adopts the window decoration if possible.
+ *
+ * @param windowDecor the potential window decoration to adopt
+ * @return the window decoration if it can be adopted, or {@code null} otherwise.
+ */
+ T adoptWindowDecoration(@Nullable AutoCloseable windowDecor);
/**
* Notifies a task info update on the given task, with the window decoration created previously
@@ -46,4 +71,18 @@ public interface WindowDecorViewModel<T extends AutoCloseable> {
* @param windowDecoration the window decoration created for the task
*/
void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo, T windowDecoration);
+
+ /**
+ * Notifies a transition is about to start about the given task to give the window decoration a
+ * chance to prepare for this transition.
+ *
+ * @param startT the start transaction to be applied before the transition
+ * @param finishT the finish transaction to restore states after the transition
+ * @param windowDecoration the window decoration created for the task
+ */
+ void setupWindowDecorationForTransition(
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT,
+ T windowDecoration);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 4855fbd5ba7a..4380bdc36417 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -140,8 +140,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
abstract void relayout(RunningTaskInfo taskInfo);
void relayout(RunningTaskInfo taskInfo, int layoutResId, T rootView, float captionHeightDp,
- Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction t,
- WindowContainerTransaction wct, RelayoutResult<T> outResult) {
+ Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT, WindowContainerTransaction wct,
+ RelayoutResult<T> outResult) {
outResult.reset();
final Configuration oldTaskConfig = mTaskInfo.getConfiguration();
@@ -151,7 +152,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
if (!mTaskInfo.isVisible) {
releaseViews();
- t.hide(mTaskSurface);
+ finishT.hide(mTaskSurface);
return;
}
@@ -192,7 +193,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
.setParent(mTaskSurface)
.build();
- t.setTrustedOverlay(mDecorationContainerSurface, true);
+ startT.setTrustedOverlay(mDecorationContainerSurface, true);
}
final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
@@ -205,7 +206,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
outResult.mHeight = taskBounds.height()
+ (int) (outsetsDp.bottom * outResult.mDensity)
- decorContainerOffsetY;
- t.setPosition(mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY)
+ startT.setPosition(
+ mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY)
.setWindowCrop(mDecorationContainerSurface, outResult.mWidth, outResult.mHeight)
.setLayer(mDecorationContainerSurface, mTaskInfo.numActivities + 1)
.show(mDecorationContainerSurface);
@@ -225,7 +227,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
- t.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
+ startT.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
.setShadowRadius(mTaskBackgroundSurface, shadowRadius)
.setColor(mTaskBackgroundSurface, mTmpColor);
@@ -264,9 +266,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
decorContainerOffsetY,
outResult.mWidth + decorContainerOffsetX,
outResult.mHeight + decorContainerOffsetY);
- t.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
- .setCrop(mTaskSurface, mTaskSurfaceCrop)
- .show(mTaskSurface);
+ startT.show(mTaskSurface);
+ finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
+ .setCrop(mTaskSurface, mTaskSurfaceCrop);
}
/**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java
index 219e5ab6c651..6cd5677db2c3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellInitTest.java
@@ -31,7 +31,7 @@ import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.draganddrop.DragAndDropController;
-import com.android.wm.shell.freeform.FreeformTaskListener;
+import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.pip.phone.PipTouchHandler;
@@ -71,7 +71,7 @@ public class ShellInitTest extends ShellTestCase {
@Mock private FullscreenTaskListener mFullscreenTaskListener;
@Mock private Optional<UnfoldAnimationController> mUnfoldAnimationController;
@Mock private Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
- @Mock private Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional;
+ @Mock private Optional<FreeformComponents> mFreeformComponentsOptional;
@Mock private Optional<RecentTasksController> mRecentTasks;
@Mock private Optional<ActivityEmbeddingController> mActivityEmbeddingController;
@Mock private Transitions mTransitions;
@@ -87,7 +87,7 @@ public class ShellInitTest extends ShellTestCase {
mDisplayInsetsController, mDragAndDropController, mShellTaskOrganizer,
mKidsModeTaskOrganizer, mBubblesOptional, mSplitScreenOptional,
mPipTouchHandlerOptional, mFullscreenTaskListener, mUnfoldAnimationController,
- mUnfoldTransitionHandler, mFreeformTaskListenerOptional, mRecentTasks,
+ mUnfoldTransitionHandler, mFreeformComponentsOptional, mRecentTasks,
mActivityEmbeddingController, mTransitions, mStartingWindow, mMainExecutor);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index d1b837ef42f1..b318bb26a51d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -98,11 +98,13 @@ public class WindowDecorationTests extends ShellTestCase {
private WindowContainerTransaction mMockWindowContainerTransaction;
private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
- private SurfaceControl.Transaction mMockSurfaceControlTransaction;
+ private SurfaceControl.Transaction mMockSurfaceControlStartT;
+ private SurfaceControl.Transaction mMockSurfaceControlFinishT;
@Before
public void setUp() {
- mMockSurfaceControlTransaction = createMockSurfaceControlTransaction();
+ mMockSurfaceControlStartT = createMockSurfaceControlTransaction();
+ mMockSurfaceControlFinishT = createMockSurfaceControlTransaction();
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any(), anyBoolean());
@@ -149,7 +151,7 @@ public class WindowDecorationTests extends ShellTestCase {
verify(mMockSurfaceControlViewHostFactory, never())
.create(any(), any(), any(), anyBoolean());
- verify(mMockSurfaceControlTransaction).hide(taskSurface);
+ verify(mMockSurfaceControlFinishT).hide(taskSurface);
assertNull(mRelayoutResult.mRootView);
}
@@ -192,16 +194,16 @@ public class WindowDecorationTests extends ShellTestCase {
verify(decorContainerSurfaceBuilder).setParent(taskSurface);
verify(decorContainerSurfaceBuilder).setContainerLayer();
- verify(mMockSurfaceControlTransaction).setTrustedOverlay(decorContainerSurface, true);
- verify(mMockSurfaceControlTransaction).setPosition(decorContainerSurface, -20, -40);
- verify(mMockSurfaceControlTransaction).setWindowCrop(decorContainerSurface, 380, 220);
+ verify(mMockSurfaceControlStartT).setTrustedOverlay(decorContainerSurface, true);
+ verify(mMockSurfaceControlStartT).setPosition(decorContainerSurface, -20, -40);
+ verify(mMockSurfaceControlStartT).setWindowCrop(decorContainerSurface, 380, 220);
verify(taskBackgroundSurfaceBuilder).setParent(taskSurface);
verify(taskBackgroundSurfaceBuilder).setEffectLayer();
- verify(mMockSurfaceControlTransaction).setWindowCrop(taskBackgroundSurface, 300, 100);
- verify(mMockSurfaceControlTransaction)
+ verify(mMockSurfaceControlStartT).setWindowCrop(taskBackgroundSurface, 300, 100);
+ verify(mMockSurfaceControlStartT)
.setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f});
- verify(mMockSurfaceControlTransaction).setShadowRadius(taskBackgroundSurface, 10);
+ verify(mMockSurfaceControlStartT).setShadowRadius(taskBackgroundSurface, 10);
verify(mMockSurfaceControlViewHostFactory)
.create(any(), eq(defaultDisplay), any(), anyBoolean());
@@ -218,11 +220,11 @@ public class WindowDecorationTests extends ShellTestCase {
new int[] { InsetsState.ITYPE_CAPTION_BAR });
}
- verify(mMockSurfaceControlTransaction)
+ verify(mMockSurfaceControlFinishT)
.setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y);
- verify(mMockSurfaceControlTransaction)
+ verify(mMockSurfaceControlFinishT)
.setCrop(taskSurface, new Rect(-20, -40, 360, 180));
- verify(mMockSurfaceControlTransaction)
+ verify(mMockSurfaceControlStartT)
.show(taskSurface);
assertEquals(380, mRelayoutResult.mWidth);
@@ -319,8 +321,8 @@ public class WindowDecorationTests extends ShellTestCase {
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
relayout(null /* taskInfo */, 0 /* layoutResId */, mMockView, CAPTION_HEIGHT_DP,
- mOutsetsDp, SHADOW_RADIUS_DP, mMockSurfaceControlTransaction,
- mMockWindowContainerTransaction, mRelayoutResult);
+ mOutsetsDp, SHADOW_RADIUS_DP, mMockSurfaceControlStartT,
+ mMockSurfaceControlFinishT, mMockWindowContainerTransaction, mRelayoutResult);
}
}
}