summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}
}
}