Fix action mode animation on recreations

Currently if an action mode is started in onCreate()
it will fade in. This isn't ideal though, especially
since Activities are recreated routinely with
multi-window and resizable Activities. In that instance
we fade it in on every recreate.

This CL fixes this in both the decor and toolbar action
modes to only fade in if the decor has been laid out.

BUG: 29036694
Change-Id: Id75ac73bcf00bc15c91734a03195332dc118578c
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
index 014605c..fbf0144 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
@@ -770,21 +770,27 @@
                                     mActionModeView,
                                     Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
                             endOnGoingFadeAnimation();
-                            ViewCompat.setAlpha(mActionModeView, 0f);
-                            mFadeAnim = ViewCompat.animate(mActionModeView).alpha(1f);
-                            mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() {
-                                @Override
-                                public void onAnimationEnd(View view) {
-                                    ViewCompat.setAlpha(mActionModeView, 1f);
-                                    mFadeAnim.setListener(null);
-                                    mFadeAnim = null;
-                                }
 
-                                @Override
-                                public void onAnimationStart(View view) {
-                                    mActionModeView.setVisibility(View.VISIBLE);
-                                }
-                            });
+                            if (shouldAnimateActionModeView()) {
+                                ViewCompat.setAlpha(mActionModeView, 0f);
+                                mFadeAnim = ViewCompat.animate(mActionModeView).alpha(1f);
+                                mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() {
+                                    @Override
+                                    public void onAnimationStart(View view) {
+                                        mActionModeView.setVisibility(View.VISIBLE);
+                                    }
+
+                                    @Override
+                                    public void onAnimationEnd(View view) {
+                                        ViewCompat.setAlpha(mActionModeView, 1f);
+                                        mFadeAnim.setListener(null);
+                                        mFadeAnim = null;
+                                    }
+                                });
+                            } else {
+                                ViewCompat.setAlpha(mActionModeView, 1f);
+                                mActionModeView.setVisibility(View.VISIBLE);
+                            }
                         }
                     };
                 } else {
@@ -807,26 +813,38 @@
                     mode.invalidate();
                     mActionModeView.initForMode(mode);
                     mActionMode = mode;
-                    ViewCompat.setAlpha(mActionModeView, 0f);
-                    mFadeAnim = ViewCompat.animate(mActionModeView).alpha(1f);
-                    mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(View view) {
-                            ViewCompat.setAlpha(mActionModeView, 1f);
-                            mFadeAnim.setListener(null);
-                            mFadeAnim = null;
-                        }
 
-                        @Override
-                        public void onAnimationStart(View view) {
-                            mActionModeView.setVisibility(View.VISIBLE);
-                            mActionModeView.sendAccessibilityEvent(
-                                    AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-                            if (mActionModeView.getParent() != null) {
-                                ViewCompat.requestApplyInsets((View) mActionModeView.getParent());
+                    if (shouldAnimateActionModeView()) {
+                        ViewCompat.setAlpha(mActionModeView, 0f);
+                        mFadeAnim = ViewCompat.animate(mActionModeView).alpha(1f);
+                        mFadeAnim.setListener(new ViewPropertyAnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationStart(View view) {
+                                mActionModeView.setVisibility(View.VISIBLE);
+                                mActionModeView.sendAccessibilityEvent(
+                                        AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+                                if (mActionModeView.getParent() != null) {
+                                    ViewCompat.requestApplyInsets((View) mActionModeView.getParent());
+                                }
                             }
+
+                            @Override
+                            public void onAnimationEnd(View view) {
+                                ViewCompat.setAlpha(mActionModeView, 1f);
+                                mFadeAnim.setListener(null);
+                                mFadeAnim = null;
+                            }
+                        });
+                    } else {
+                        ViewCompat.setAlpha(mActionModeView, 1f);
+                        mActionModeView.setVisibility(View.VISIBLE);
+                        mActionModeView.sendAccessibilityEvent(
+                                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+                        if (mActionModeView.getParent() != null) {
+                            ViewCompat.requestApplyInsets((View) mActionModeView.getParent());
                         }
-                    });
+                    }
+
                     if (mActionModePopup != null) {
                         mWindow.getDecorView().post(mShowActionModePopup);
                     }
@@ -841,6 +859,12 @@
         return mActionMode;
     }
 
+    final boolean shouldAnimateActionModeView() {
+        // We only to animate the action mode in if the sub decor has already been laid out.
+        // If it hasn't been laid out, it hasn't been drawn to screen yet.
+        return mSubDecorInstalled && mSubDecor != null && ViewCompat.isLaidOut(mSubDecor);
+    }
+
     private void endOnGoingFadeAnimation() {
         if (mFadeAnim != null) {
             mFadeAnim.cancel();
diff --git a/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java b/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java
index af46fe6..5d4e94e 100644
--- a/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java
+++ b/v7/appcompat/src/android/support/v7/app/WindowDecorActionBar.java
@@ -853,28 +853,44 @@
             hideForActionMode();
         }
 
-        ViewPropertyAnimatorCompat fadeIn, fadeOut;
-        if (toActionMode) {
-            // We use INVISIBLE for the Toolbar to make sure that the container has a non-zero
-            // height throughout. The context view is GONE initially, so will not have been laid
-            // out when the animation starts. This can lead to the container collapsing to 0px
-            // height for a short period.
-            fadeOut = mDecorToolbar.setupAnimatorToVisibility(View.INVISIBLE,
-                    FADE_OUT_DURATION_MS);
-            fadeIn = mContextView.setupAnimatorToVisibility(View.VISIBLE,
-                    FADE_IN_DURATION_MS);
+        if (shouldAnimateContextView()) {
+            ViewPropertyAnimatorCompat fadeIn, fadeOut;
+            if (toActionMode) {
+                // We use INVISIBLE for the Toolbar to make sure that the container has a non-zero
+                // height throughout. The context view is GONE initially, so will not have been laid
+                // out when the animation starts. This can lead to the container collapsing to 0px
+                // height for a short period.
+                fadeOut = mDecorToolbar.setupAnimatorToVisibility(View.INVISIBLE,
+                        FADE_OUT_DURATION_MS);
+                fadeIn = mContextView.setupAnimatorToVisibility(View.VISIBLE,
+                        FADE_IN_DURATION_MS);
+            } else {
+                fadeIn = mDecorToolbar.setupAnimatorToVisibility(View.VISIBLE,
+                        FADE_IN_DURATION_MS);
+                fadeOut = mContextView.setupAnimatorToVisibility(View.GONE,
+                        FADE_OUT_DURATION_MS);
+            }
+            ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
+            set.playSequentially(fadeOut, fadeIn);
+            set.start();
         } else {
-            fadeIn = mDecorToolbar.setupAnimatorToVisibility(View.VISIBLE,
-                    FADE_IN_DURATION_MS);
-            fadeOut = mContextView.setupAnimatorToVisibility(View.GONE,
-                    FADE_OUT_DURATION_MS);
+            if (toActionMode) {
+                mDecorToolbar.setVisibility(View.INVISIBLE);
+                mContextView.setVisibility(View.VISIBLE);
+            } else {
+                mDecorToolbar.setVisibility(View.VISIBLE);
+                mContextView.setVisibility(View.GONE);
+            }
         }
-        ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
-        set.playSequentially(fadeOut, fadeIn);
-        set.start();
         // mTabScrollView's visibility is not affected by action mode.
     }
 
+    private boolean shouldAnimateContextView() {
+        // We only to animate the action mode in if the container view has already been laid out.
+        // If it hasn't been laid out, it hasn't been drawn to screen yet.
+        return ViewCompat.isLaidOut(mContainerView);
+    }
+
     public Context getThemedContext() {
         if (mThemedContext == null) {
             TypedValue outValue = new TypedValue();