diff options
3 files changed, 49 insertions, 12 deletions
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 ac95d4bc63d1..f58719b225a4 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 @@ -191,15 +191,19 @@ public class FreeformTaskListener<T extends AutoCloseable> * * @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 + * @return {@code true} if it creates the window decoration; {@code false} otherwise */ - void createWindowDecoration( + boolean createWindowDecoration( TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash()); + if (state.mWindowDecoration != null) { + return false; + } state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration( state.mTaskInfo, state.mLeash, startT, finishT); + return true; } /** @@ -222,6 +226,9 @@ public class FreeformTaskListener<T extends AutoCloseable> windowDecor = mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId); } + if (windowDecor == null) { + return null; + } mWindowDecorationViewModel.setupWindowDecorationForTransition( taskInfo, startT, finishT, windowDecor); return windowDecor; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java index a780ec102ea9..17d60671e964 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java @@ -26,6 +26,7 @@ import android.util.Log; import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; +import android.window.WindowContainerToken; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -80,6 +81,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs @NonNull SurfaceControl.Transaction startT, @NonNull SurfaceControl.Transaction finishT) { final ArrayList<AutoCloseable> windowDecors = new ArrayList<>(); + final ArrayList<WindowContainerToken> taskParents = new ArrayList<>(); for (TransitionInfo.Change change : info.getChanges()) { if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) { continue; @@ -89,9 +91,22 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs if (taskInfo == null || taskInfo.taskId == -1) { continue; } + // Filter out non-leaf tasks. Freeform/fullscreen don't nest tasks, but split-screen + // does, so this prevents adding duplicate captions in that scenario. + if (change.getParent() != null + && info.getChange(change.getParent()).getTaskInfo() != null) { + // This logic relies on 2 assumptions: 1 is that child tasks will be visited before + // parents (due to how z-order works). 2 is that no non-tasks are interleaved + // between tasks (hierarchically). + taskParents.add(change.getContainer()); + } + if (taskParents.contains(change.getContainer())) { + continue; + } switch (change.getMode()) { case WindowManager.TRANSIT_OPEN: + case WindowManager.TRANSIT_TO_FRONT: onOpenTransitionReady(change, startT, finishT); break; case WindowManager.TRANSIT_CLOSE: { @@ -154,20 +169,28 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs boolean adopted = false; final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); - if (type == Transitions.TRANSIT_MAXIMIZE - && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { windowDecor = mFreeformTaskListener.giveWindowDecoration( change.getTaskInfo(), startT, finishT); - adopted = mFullscreenTaskListener.adoptWindowDecoration( - change, startT, finishT, windowDecor); + if (windowDecor != null) { + adopted = mFullscreenTaskListener.adoptWindowDecoration( + change, startT, finishT, windowDecor); + } else { + // will return false if it already has the window decor. + adopted = mFullscreenTaskListener.createWindowDecoration(change, startT, finishT); + } } - if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE - && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) { + if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) { windowDecor = mFullscreenTaskListener.giveWindowDecoration( change.getTaskInfo(), startT, finishT); - adopted = mFreeformTaskListener.adoptWindowDecoration( - change, startT, finishT, windowDecor); + if (windowDecor != null) { + adopted = mFreeformTaskListener.adoptWindowDecoration( + change, startT, finishT, windowDecor); + } else { + // will return false if it already has the window decor. + adopted = mFreeformTaskListener.createWindowDecoration(change, startT, finishT); + } } if (!adopted) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java index 7d1259a732c9..76e296bb8c61 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java @@ -173,16 +173,23 @@ public class FullscreenTaskListener<T extends AutoCloseable> * * @param change the change of this task transition that needs to have the task layer as the * leash + * @return {@code true} if a decoration was actually created. */ - public void createWindowDecoration(TransitionInfo.Change change, + public boolean createWindowDecoration(TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash()); - if (!mWindowDecorViewModelOptional.isPresent()) return; + if (!mWindowDecorViewModelOptional.isPresent()) return false; + if (state.mWindowDecoration != null) { + // Already has a decoration. + return false; + } T newWindowDecor = mWindowDecorViewModelOptional.get().createWindowDecoration( state.mTaskInfo, state.mLeash, startT, finishT); if (newWindowDecor != null) { state.mWindowDecoration = newWindowDecor; + return true; } + return false; } /** |