Put PIP windows above transition animations.

PIP activities are already on top of everything else, but during
animation we increase the layer of the animated window for the duration
of the animation and it may cover the PIP. By forcing the same
adjustment on PIP windows we will keep them above animating windows.

Bug: 26015827
Change-Id: I8f7a87f41fed24b3e520fb599a94cf24cc2eeb50
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 798deb1..98b5bbd 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -548,6 +548,10 @@
         public static boolean canReceiveKeys(int stackId) {
             return stackId != PINNED_STACK_ID;
         }
+
+        public static boolean isAlwaysOnTop(int stackId) {
+            return stackId == PINNED_STACK_ID;
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 36a7cee..e0cfc88 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -538,9 +538,8 @@
 
         if (addIndex > 0) {
             final ActivityStack topStack = mStacks.get(addIndex - 1);
-            if (topStack.mStackId == PINNED_STACK_ID && topStack != this) {
-                // The pinned stack is always the top most stack (always-on-top).
-                // So, stack is moved just below the pinned stack.
+            if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) {
+                // If the top stack is always on top, we move this stack just below it.
                 addIndex--;
             }
         }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4bbf586..898a9a4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -237,8 +237,8 @@
     }
 
     void moveStack(TaskStack stack, boolean toTop) {
-        if (stack.mStackId == PINNED_STACK_ID && !toTop) {
-            // Pinned stack is always-on-top silly...
+        if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
+            // This stack is always-on-top silly...
             Slog.w(TAG, "Ignoring move of always-on-top stack=" + stack + " to bottom");
             return;
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f25f1e3..8259fa7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -58,6 +58,8 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
@@ -8652,14 +8654,7 @@
             } else if (wtoken != null) {
                 winAnimator.mAnimLayer =
                         w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
-                if (wtoken.mWillReplaceWindow && wtoken.mReplacingWindow != w
-                        && wtoken.mAnimateReplacingWindow) {
-                    // We know that we will be animating a relaunching window in the near future,
-                    // which will receive a z-order increase. We want the replaced window to
-                    // immediately receive the same treatment, e.g. to be above the dock divider.
-                    w.mLayer += TYPE_LAYER_OFFSET;
-                    winAnimator.mAnimLayer += TYPE_LAYER_OFFSET;
-                }
+                forceHigherLayerIfNeeded(w, winAnimator, wtoken);
             } else {
                 winAnimator.mAnimLayer = w.mLayer;
             }
@@ -8696,6 +8691,30 @@
         }
     }
 
+    private void forceHigherLayerIfNeeded(WindowState w, WindowStateAnimator winAnimator,
+            AppWindowToken wtoken) {
+        boolean force = false;
+        if (wtoken.mWillReplaceWindow && wtoken.mReplacingWindow != w
+                && wtoken.mAnimateReplacingWindow) {
+            // We know that we will be animating a relaunching window in the near future,
+            // which will receive a z-order increase. We want the replaced window to
+            // immediately receive the same treatment, e.g. to be above the dock divider.
+            force = true;
+        }
+        if (!force) {
+            final TaskStack stack = w.getStack();
+            if (stack != null && StackId.isAlwaysOnTop(stack.mStackId)) {
+                // If the window's stack is always on top, we want to make it above other windows
+                // also when these windows are animating.
+                force = true;
+            }
+        }
+        if (force) {
+            w.mLayer += TYPE_LAYER_OFFSET;
+            winAnimator.mAnimLayer += TYPE_LAYER_OFFSET;
+        }
+    }
+
     void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
         // If the screen is currently frozen or off, then keep
         // it frozen/off until this window draws at its new