Merge "Adjust caption observer for desktop transition" into tm-qpr-dev am: 556ecc8da9 am: 0ac4d2e85d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19973036

Change-Id: Ibe20c26f760b42b0e4f50afe62775b3571b72b50
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
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 ac95d4b..f58719b 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 @@
      *
      * @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 @@
             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 a780ec1..17d6067 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.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 @@
             @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 @@
             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 @@
 
         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 7d1259a..76e296b 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 @@
      *
      * @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;
     }
 
     /**