Animate the dock divider appearance/disappearance.

We want to animate the dock divider appearance only after the entrance
animation of the docked activity finishes, so these two don't clash. For
disappearance they will animate together.

Bug: 24913915
Change-Id: Ibe5c3960f21fcc5e64039b158605fa09017c5c34
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 209751e..121ef21 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2532,6 +2532,12 @@
                     return R.anim.dock_right_enter;
                 }
             }
+        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
+            if (transit == TRANSIT_ENTER) {
+                return R.anim.fade_in;
+            } else if (transit == TRANSIT_EXIT) {
+                return R.anim.fade_out;
+            }
         }
 
         if (transit == TRANSIT_PREVIEW_DONE) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9143097..58ba24e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -274,11 +274,11 @@
             // If we're animating with a saved surface, we're already visible.
             // Return true so that the alpha doesn't get cleared.
             if (!win.mAppFreezing
-                    && (win.mViewVisibility == View.VISIBLE
-                    || mAnimatingWithSavedSurface
-                    || (win.mWinAnimator.isAnimating() &&
-                            !service.mAppTransition.isTransitionSet()))
-                    && !win.mDestroying && win.isDrawnLw()) {
+                    && (win.mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface
+                            || (win.mWinAnimator.isAnimating()
+                                    && !service.mAppTransition.isTransitionSet()))
+                    && !win.mDestroying
+                    && win.isDrawnLw()) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index eafc3c6..77ae35a 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -122,10 +122,10 @@
         if (forceUpdate && mView != null) {
             removeDivider();
         }
-        TaskStack stack = mDisplayContent.getDockedStackLocked();
-        if (stack != null && mView == null) {
+        TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID);
+        if (stack != null && stack.hasWindowWithFinalVisibility() && mView == null) {
             addDivider(configuration);
-        } else if (stack == null && mView != null) {
+        } else if ((stack == null || !stack.isVisibleLocked()) && mView != null) {
             removeDivider();
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index f72384c..bb3d6f7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -700,4 +700,26 @@
         }
         return false;
     }
+
+    /**
+     * Returns true if this stack has a window that is fully visible, doesn't perform an entry
+     * animation and is just positioned where it's supposed to be.
+     */
+    boolean hasWindowWithFinalVisibility() {
+        for (int i = mTasks.size() - 1; i >= 0; i--) {
+            Task task = mTasks.get(i);
+            for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
+                final AppWindowToken token = task.mAppTokens.get(j);
+                if (token.mAppAnimator.animating || token.mWillReplaceWindow) {
+                    continue;
+                }
+                WindowState win = token.findMainWindow();
+                if (win != null && !win.mWinAnimator.mEnterAnimationPending
+                        && !win.mWinAnimator.mEnteringAnimation) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ec97ba8..9f37169 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -437,11 +437,16 @@
             mWin.mChildWindows.get(i).mWinAnimator.finishExit();
         }
 
-        if (mEnteringAnimation && mWin.mAppToken == null) {
-            try {
-                mEnteringAnimation = false;
-                mWin.mClient.dispatchWindowShown();
-            } catch (RemoteException e) {
+        if (mEnteringAnimation) {
+            mEnteringAnimation = false;
+            mService.requestTraversal();
+            // System windows don't have an activity and an app token as a result, but need a way
+            // to be informed about their entrance animation end.
+            if (mWin.mAppToken == null) {
+                try {
+                    mWin.mClient.dispatchWindowShown();
+                } catch (RemoteException e) {
+                }
             }
         }