Revert "Revert "Speed up All Apps -> Workspace transition""

- also, undo enabling hardware layers for
    scroll indicator, which could have caused
    slowness
- fix bug where scroll indicator was not seen
    after the first visit to all apps
- eliminate a some needless hardware layer redraws
- making items under All Apps invisible when we're
    in All Apps
- making workspace spaces invisible if their alpha is 0
    to prevent more hardware layer rebuilding

This reverts commit 9753d13c7bda09c1203c611ac6717021037f39c3.

Change-Id: Ib908ae0b456b2d4b8a171991a95f20aea4749da1
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index 023946b..a5964df 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -347,38 +347,46 @@
 
     /* LauncherTransitionable overrides */
     @Override
-    public void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace) {
+    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
         mInTransition = true;
-        boolean animated = (animation != null);
 
-        mContent.setVisibility(VISIBLE);
+        if (toWorkspace) {
+            // Going from All Apps -> Workspace
+            setVisibilityOfSiblingsWithLowerZOrder(VISIBLE);
+        } else {
+            // Going from Workspace -> All Apps
+            mContent.setVisibility(VISIBLE);
 
-        if (!toWorkspace) {
             // Make sure the current page is loaded (we start loading the side pages after the
             // transition to prevent slowing down the animation)
             mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
-        }
-        if (animated) {
-            enableAndBuildHardwareLayer();
+
+            if (!LauncherApplication.isScreenLarge()) {
+                mAppsCustomizePane.showScrollingIndicator(true);
+            }
         }
 
-        if (!toWorkspace && !LauncherApplication.isScreenLarge()) {
-            mAppsCustomizePane.showScrollingIndicator(false);
-        }
         if (mResetAfterTransition) {
             mAppsCustomizePane.reset();
             mResetAfterTransition = false;
         }
+
+        if (animated) {
+            enableAndBuildHardwareLayer();
+        }
     }
 
     @Override
-    public void onLauncherTransitionEnd(Launcher l, Animator animation, boolean toWorkspace) {
+    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
         mInTransition = false;
-        if (animation != null) {
+        if (animated) {
             setLayerType(LAYER_TYPE_NONE, null);
         }
 
         if (!toWorkspace) {
+            // Going from Workspace -> All Apps
+            setVisibilityOfSiblingsWithLowerZOrder(INVISIBLE);
+
             // Dismiss the workspace cling and show the all apps cling (if not already shown)
             l.dismissWorkspaceCling(null);
             mAppsCustomizePane.showAllAppsCling();
@@ -392,6 +400,26 @@
         }
     }
 
+    private void setVisibilityOfSiblingsWithLowerZOrder(int visibility) {
+        ViewGroup parent = (ViewGroup) getParent();
+        final int count = parent.getChildCount();
+        if (!isChildrenDrawingOrderEnabled()) {
+            for (int i = 0; i < count; i++) {
+                final View child = parent.getChildAt(i);
+                if (child == this) {
+                    break;
+                } else {
+                    if (child.getVisibility() == GONE) {
+                        continue;
+                    }
+                    child.setVisibility(visibility);
+                }
+            }
+        } else {
+            throw new RuntimeException("Failed; can't get z-order of views");
+        }
+    }
+
     public void onWindowVisible() {
         if (getVisibility() == VISIBLE) {
             mContent.setVisibility(VISIBLE);
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 8850cf8..92a3d08 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -606,9 +606,6 @@
             // Resets the previous all apps icon press state
             mAppsCustomizeContent.resetDrawableState();
         }
-        // When we resume Launcher, a different Activity might be responsible for the app
-        // market intent, so refresh the icon
-        updateAppMarketIcon();
     }
 
     @Override
@@ -619,6 +616,16 @@
     }
 
     @Override
+    protected void onStart() {
+        super.onStart();
+        // When Launcher comes back to foreground, a different Activity might be responsible for
+        // the app market intent, so refresh the icon
+        // We don't do this in onResume() because onResume() is triggered every time the home
+        // button is pressed (even if we were already in Launcher)
+        updateAppMarketIcon();
+    }
+
+    @Override
     public Object onRetainNonConfigurationInstance() {
         // Flag the loader to stop early before switching
         mModel.stopLoader();
@@ -2213,6 +2220,18 @@
         }
     }
 
+    private void dispatchOnLauncherTransitionStart(View v, boolean animated, boolean toWorkspace) {
+        if (v instanceof LauncherTransitionable) {
+            ((LauncherTransitionable) v).onLauncherTransitionStart(this, animated, toWorkspace);
+        }
+    }
+
+    private void dispatchOnLauncherTransitionEnd(View v, boolean animated, boolean toWorkspace) {
+        if (v instanceof LauncherTransitionable) {
+            ((LauncherTransitionable) v).onLauncherTransitionEnd(this, animated, toWorkspace);
+        }
+    }
+
     /**
      * Things to test when changing the following seven functions.
      *   - Home from workspace
@@ -2258,7 +2277,7 @@
      * Assumes that the view to show is anchored at either the very top or very bottom
      * of the screen.
      */
-    private void showAppsCustomizeHelper(boolean animated, final boolean springLoaded) {
+    private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded) {
         if (mStateAnimation != null) {
             mStateAnimation.cancel();
             mStateAnimation = null;
@@ -2269,6 +2288,7 @@
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
         final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime);
         final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
+        final View fromView = mWorkspace;
         final View toView = mAppsCustomizeTabHost;
         final int startDelay =
                 res.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger);
@@ -2315,10 +2335,8 @@
                 }
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    if (toView instanceof LauncherTransitionable) {
-                        ((LauncherTransitionable) toView).onLauncherTransitionEnd(instance,
-                                scaleAnim, false);
-                    }
+                    dispatchOnLauncherTransitionEnd(fromView, animated, false);
+                    dispatchOnLauncherTransitionEnd(toView, animated, false);
 
                     if (!springLoaded && !LauncherApplication.isScreenLarge()) {
                         // Hide the workspace scrollbar
@@ -2341,14 +2359,14 @@
             }
 
             boolean delayAnim = false;
-            LauncherTransitionable lt = (LauncherTransitionable) toView;
             final ViewTreeObserver observer;
 
-            lt.onLauncherTransitionStart(instance, mStateAnimation, false);
+            dispatchOnLauncherTransitionStart(fromView, animated, false);
+            dispatchOnLauncherTransitionStart(toView, animated, false);
 
             // If any of the objects being animated haven't been measured/laid out
             // yet, delay the animation until we get a layout pass
-            if ((lt.getContent().getMeasuredWidth() == 0) ||
+            if ((((LauncherTransitionable) toView).getContent().getMeasuredWidth() == 0) ||
                     (mWorkspace.getMeasuredWidth() == 0) ||
                     (toView.getMeasuredWidth() == 0)) {
                 observer = mWorkspace.getViewTreeObserver();
@@ -2387,16 +2405,16 @@
             toView.setScaleY(1.0f);
             toView.setVisibility(View.VISIBLE);
             toView.bringToFront();
-            if (toView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) toView).onLauncherTransitionStart(instance, null, false);
-                ((LauncherTransitionable) toView).onLauncherTransitionEnd(instance, null, false);
 
-                if (!springLoaded && !LauncherApplication.isScreenLarge()) {
-                    // Hide the workspace scrollbar
-                    mWorkspace.hideScrollingIndicator(true);
-                    hideDockDivider();
-                }
+            if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+                // Hide the workspace scrollbar
+                mWorkspace.hideScrollingIndicator(true);
+                hideDockDivider();
             }
+            dispatchOnLauncherTransitionStart(fromView, animated, false);
+            dispatchOnLauncherTransitionEnd(fromView, animated, false);
+            dispatchOnLauncherTransitionStart(toView, animated, false);
+            dispatchOnLauncherTransitionEnd(toView, animated, false);
             updateWallpaperVisibility(false);
         }
     }
@@ -2408,12 +2426,12 @@
      */
     private void hideAppsCustomizeHelper(State toState, final boolean animated,
             final boolean springLoaded, final Runnable onCompleteRunnable) {
+
         if (mStateAnimation != null) {
             mStateAnimation.cancel();
             mStateAnimation = null;
         }
         Resources res = getResources();
-        final Launcher instance = this;
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
         final int fadeOutDuration =
@@ -2421,6 +2439,7 @@
         final float scaleFactor = (float)
                 res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
         final View fromView = mAppsCustomizeTabHost;
+        final View toView = mWorkspace;
         Animator workspaceAnim = null;
 
         if (toState == State.WORKSPACE) {
@@ -2451,19 +2470,18 @@
                 .setDuration(fadeOutDuration);
             alphaAnim.setInterpolator(new AccelerateDecelerateInterpolator());
 
-            if (fromView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) fromView).onLauncherTransitionStart(instance, alphaAnim,
-                        true);
-            }
-            alphaAnim.addListener(new AnimatorListenerAdapter() {
+            mStateAnimation = new AnimatorSet();
+
+            dispatchOnLauncherTransitionStart(fromView, animated, true);
+            dispatchOnLauncherTransitionStart(toView, animated, true);
+
+            mStateAnimation.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     updateWallpaperVisibility(true);
                     fromView.setVisibility(View.GONE);
-                    if (fromView instanceof LauncherTransitionable) {
-                        ((LauncherTransitionable) fromView).onLauncherTransitionEnd(instance,
-                                alphaAnim, true);
-                    }
+                    dispatchOnLauncherTransitionEnd(fromView, animated, true);
+                    dispatchOnLauncherTransitionEnd(toView, animated, true);
                     mWorkspace.hideScrollingIndicator(false);
                     if (onCompleteRunnable != null) {
                         onCompleteRunnable.run();
@@ -2471,7 +2489,6 @@
                 }
             });
 
-            mStateAnimation = new AnimatorSet();
             mStateAnimation.playTogether(scaleAnim, alphaAnim);
             if (workspaceAnim != null) {
                 mStateAnimation.play(workspaceAnim);
@@ -2479,10 +2496,10 @@
             mStateAnimation.start();
         } else {
             fromView.setVisibility(View.GONE);
-            if (fromView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) fromView).onLauncherTransitionStart(instance, null, true);
-                ((LauncherTransitionable) fromView).onLauncherTransitionEnd(instance, null, true);
-            }
+            dispatchOnLauncherTransitionStart(fromView, animated, true);
+            dispatchOnLauncherTransitionEnd(fromView, animated, true);
+            dispatchOnLauncherTransitionStart(toView, animated, true);
+            dispatchOnLauncherTransitionEnd(toView, animated, true);
             mWorkspace.hideScrollingIndicator(false);
         }
     }
@@ -3429,6 +3446,6 @@
 
 interface LauncherTransitionable {
     View getContent();
-    void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace);
-    void onLauncherTransitionEnd(Launcher l, Animator animation, boolean toWorkspace);
+    void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace);
+    void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
 }
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 9a140d2..184ea7a 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -176,6 +176,8 @@
     private int mScrollIndicatorPaddingLeft;
     private int mScrollIndicatorPaddingRight;
     private boolean mHasScrollIndicator = true;
+    private boolean mShouldShowScrollIndicator = false;
+    private boolean mShouldShowScrollIndicatorImmediately = false;
     protected static final int sScrollIndicatorFadeInDuration = 150;
     protected static final int sScrollIndicatorFadeOutDuration = 650;
     protected static final int sScrollIndicatorFlashDuration = 650;
@@ -767,7 +769,8 @@
                 for (int i = getChildCount() - 1; i >= 0; i--) {
                     final View v = getPageAt(i);
 
-                    if (leftScreen <= i && i <= rightScreen) {
+                    if (leftScreen <= i && i <= rightScreen &&
+                            v.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD) {
                         v.setVisibility(VISIBLE);
                         drawChild(canvas, v, drawingTime);
                     } else {
@@ -1705,9 +1708,12 @@
     }
 
     protected void showScrollingIndicator(boolean immediately) {
+        mShouldShowScrollIndicator = true;
+        mShouldShowScrollIndicatorImmediately = true;
         if (getChildCount() <= 1) return;
         if (!isScrollingIndicatorEnabled()) return;
 
+        mShouldShowScrollIndicator = false;
         getScrollingIndicator();
         if (mScrollIndicator != null) {
             // Fade the indicator in
@@ -1779,6 +1785,9 @@
         if (mScrollIndicator != null) {
             updateScrollingIndicatorPosition();
         }
+        if (mShouldShowScrollIndicator) {
+            showScrollingIndicator(mShouldShowScrollIndicatorImmediately);
+        }
     }
 
     private void updateScrollingIndicatorPosition() {
@@ -1805,7 +1814,6 @@
             indicatorPos += indicatorCenterOffset;
         }
         mScrollIndicator.setTranslationX(indicatorPos);
-        mScrollIndicator.invalidate();
     }
 
     public void showScrollIndicatorTrack() {
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
index 3a7f24b..03ca38f 100644
--- a/src/com/android/launcher2/SearchDropTargetBar.java
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -129,14 +129,26 @@
             @Override
             public void onAnimationStart(Animator animation) {
                 mQSBSearchBar.setVisibility(View.VISIBLE);
+                mQSBSearchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mQSBSearchBar.setLayerType(View.LAYER_TYPE_NONE, null);
             }
         });
         mQSBSearchBarFadeOutAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 0f);
         mQSBSearchBarFadeOutAnim.setDuration(sTransitionOutDuration);
         mQSBSearchBarFadeOutAnim.addListener(new AnimatorListenerAdapter() {
             @Override
+            public void onAnimationStart(Animator animation) {
+                mQSBSearchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            }
+
+            @Override
             public void onAnimationEnd(Animator animation) {
                 mQSBSearchBar.setVisibility(View.INVISIBLE);
+                mQSBSearchBar.setLayerType(View.LAYER_TYPE_NONE, null);
             }
         });
     }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 4e731a2..f61917f 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -17,8 +17,6 @@
 package com.android.launcher2;
 
 import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
@@ -26,6 +24,7 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.app.AlertDialog;
 import android.app.WallpaperManager;
+import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ClipData;
@@ -57,6 +56,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.View.MeasureSpec;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -77,7 +77,7 @@
  */
 public class Workspace extends SmoothPagedView
         implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
-        DragController.DragListener {
+        DragController.DragListener, LauncherTransitionable {
     @SuppressWarnings({"UnusedDeclaration"})
     private static final String TAG = "Launcher.Workspace";
 
@@ -159,8 +159,6 @@
     private State mState = State.NORMAL;
     private boolean mIsSwitchingState = false;
 
-    private AnimatorListener mChangeStateAnimationListener;
-
     boolean mAnimatingViewIntoPlace = false;
     boolean mIsDragOccuring = false;
     boolean mChildrenLayersEnabled = true;
@@ -387,20 +385,6 @@
             // In this case, we will skip drawing background protection
         }
 
-        mChangeStateAnimationListener = new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mIsSwitchingState = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mIsSwitchingState = false;
-                mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
-                updateChildrenLayersEnabled();
-            }
-        };
-
         mWallpaperOffset = new WallpaperOffsetInterpolator();
         Display display = mLauncher.getWindowManager().getDefaultDisplay();
         mDisplayWidth = display.getWidth();
@@ -1640,26 +1624,10 @@
                 cl.setBackgroundAlphaMultiplier(finalAlphaMultiplierValue);
                 cl.setAlpha(finalAlpha);
                 cl.setRotationY(rotation);
-                mChangeStateAnimationListener.onAnimationEnd(null);
             }
         }
 
         if (animated) {
-            anim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(android.animation.Animator animation) {
-                    // The above code to determine initialAlpha and finalAlpha will ensure that only
-                    // the current page is visible during (and subsequently, after) the transition
-                    // animation.  If fade adjacent pages is disabled, then re-enable the page
-                    // visibility after the transition animation.
-                    if (!mFadeInAdjacentScreens) {
-                        for (int i = 0; i < getChildCount(); i++) {
-                            final CellLayout cl = (CellLayout) getChildAt(i);
-                            cl.setAlpha(1f);
-                        }
-                    }
-                }
-            });
             for (int index = 0; index < getChildCount(); index++) {
                 final int i = index;
                 final CellLayout cl = (CellLayout) getChildAt(i);
@@ -1715,9 +1683,6 @@
                 }
             }
             anim.setStartDelay(delay);
-            // If we call this when we're not animated, onAnimationEnd is never called on
-            // the listener; make sure we only use the listener when we're actually animating
-            anim.addListener(mChangeStateAnimationListener);
         }
 
         if (stateIsSpringLoaded) {
@@ -1733,6 +1698,33 @@
         return anim;
     }
 
+    @Override
+    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+        mIsSwitchingState = true;
+    }
+
+    @Override
+    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+        mIsSwitchingState = false;
+        mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
+        updateChildrenLayersEnabled();
+        // The code in getChangeStateAnimation to determine initialAlpha and finalAlpha will ensure
+        // ensure that only the current page is visible during (and subsequently, after) the
+        // transition animation.  If fade adjacent pages is disabled, then re-enable the page
+        // visibility after the transition animation.
+        if (!mFadeInAdjacentScreens) {
+            for (int i = 0; i < getChildCount(); i++) {
+                final CellLayout cl = (CellLayout) getChildAt(i);
+                cl.setAlpha(1f);
+            }
+        }
+    }
+
+    @Override
+    public View getContent() {
+        return this;
+    }
+
     /**
      * Draw the View v into the given Canvas.
      *