diff options
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); } } } |