Some fixes for quickstep when configuration changes

> Creating the launcher animation after first draw, so that the UI is in correct state
> Using correct workspace size, when layout is not valid
> Snapping pagedView to correct page when page size changes
> Resoting to correct workspace page on rebind

Change-Id: I74e61a05aae3a3c4912d4c5c8eb4d5d036d9005a
diff --git a/quickstep/src/com/android/quickstep/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/LauncherLayoutListener.java
index 2854342..40cd3e6 100644
--- a/quickstep/src/com/android/quickstep/LauncherLayoutListener.java
+++ b/quickstep/src/com/android/quickstep/LauncherLayoutListener.java
@@ -28,15 +28,18 @@
 public class LauncherLayoutListener extends AbstractFloatingView implements Insettable {
 
     private final Launcher mLauncher;
-    private final WindowTransformSwipeHandler mHandler;
+    private WindowTransformSwipeHandler mHandler;
 
-    public LauncherLayoutListener(Launcher launcher, WindowTransformSwipeHandler handler) {
+    public LauncherLayoutListener(Launcher launcher) {
         super(launcher, null);
         mLauncher = launcher;
-        mHandler = handler;
         setVisibility(INVISIBLE);
     }
 
+    public void setHandler(WindowTransformSwipeHandler handler) {
+        mHandler = handler;
+    }
+
     @Override
     public void setInsets(Rect insets) {
         requestLayout();
@@ -45,7 +48,9 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
-        mHandler.onLauncherLayoutChanged();
+        if (mHandler != null) {
+            mHandler.onLauncherLayoutChanged();
+        }
     }
 
     @Override
@@ -57,7 +62,10 @@
     protected void handleClose(boolean animate) {
         // We dont suupport animate.
         mLauncher.getDragLayer().removeView(this);
-        mHandler.layoutListenerClosed();
+
+        if (mHandler != null) {
+            mHandler.layoutListenerClosed();
+        }
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 1351973..6416dc1 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -158,21 +158,14 @@
                 this::reset);
         mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_SCALED_SNAPSHOT_RECENTS,
                 this::reset);
-
         mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_LAUNCHER_DRAWN,
-                mLauncherDrawnCallback);
+                this::launcherFrameDrawn);
     }
 
     private void setStateOnUiThread(int stateFlag) {
         mMainExecutor.execute(() -> mStateCallback.setState(stateFlag));
     }
 
-    public void setLauncherOnDrawCallback(Runnable callback) {
-        mLauncherDrawnCallback = callback;
-        mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_LAUNCHER_DRAWN,
-                mLauncherDrawnCallback);
-    }
-
     private void initTransitionEndpoints(DeviceProfile dp) {
         mDp = dp;
         RecentsView.getPageRect(dp, mContext, mTargetRect);
@@ -206,11 +199,18 @@
             int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
             initStateCallbacks();
             mStateCallback.setState(oldState);
+            mLauncherLayoutListener.setHandler(null);
         }
         mLauncher = launcher;
 
         AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
         mControllerStateAnimation = alreadyOnHome;
+        mWasLauncherAlreadyVisible = alreadyOnHome;
+
+        mRecentsView = mLauncher.getOverviewPanel();
+        mLauncherLayoutListener = new LauncherLayoutListener(mLauncher);
+
+        final int state;
         if (mControllerStateAnimation) {
             DeviceProfile dp = mLauncher.getDeviceProfile();
             long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
@@ -218,7 +218,8 @@
                     .createAnimationToNewWorkspace(OVERVIEW, accuracy);
             mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
 
-            mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
+            state = STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN
+                    | STATE_LAUNCHER_READY;
         } else {
             TraceHelper.beginSection("WTS-init");
             launcher.getStateManager().goToState(OVERVIEW, false);
@@ -237,6 +238,7 @@
                     if (launcher != mLauncher) {
                         return;
                     }
+                    mStateCallback.setState(STATE_LAUNCHER_DRAWN);
 
                     if ((mStateCallback.getState() & STATE_LAUNCHER_DRAWN) == 0) {
                         mStateCallback.setState(STATE_LAUNCHER_DRAWN);
@@ -247,25 +249,43 @@
                     }
                 }
             });
+            state = STATE_LAUNCHER_READY;
         }
 
-        mRecentsView = mLauncher.getOverviewPanel();
         mRecentsView.showTask(mRunningTaskId);
-        mWasLauncherAlreadyVisible = alreadyOnHome;
-        mLauncherLayoutListener = new LauncherLayoutListener(mLauncher, this);
         mLauncher.getDragLayer().addView(mLauncherLayoutListener);
 
         // Optimization
-        if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
+        // We are using the internal device profile as launcher may not have got the insets yet.
+        if (!mDp.isVerticalBarLayout()) {
             // All-apps search box is visible in vertical bar layout.
             mLauncher.getAppsView().setVisibility(View.GONE);
         }
 
-        onLauncherLayoutChanged();
-        mStateCallback.setState(STATE_LAUNCHER_READY);
+        mStateCallback.setState(state);
         return true;
     }
 
+    public void setLauncherOnDrawCallback(Runnable callback) {
+        mLauncherDrawnCallback = callback;
+    }
+
+    private void launcherFrameDrawn() {
+        View rootView = mLauncher.getRootView();
+        if (rootView.getAlpha() < 1) {
+            final MultiStateCallback callback = mStateCallback;
+            rootView.animate().alpha(1)
+                    .setDuration(getFadeInDuration())
+                    .withEndAction(() -> callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE));
+        }
+        mLauncherLayoutListener.setHandler(this);
+        onLauncherLayoutChanged();
+
+        if (mLauncherDrawnCallback != null) {
+            mLauncherDrawnCallback.run();
+        }
+    }
+
     public void updateInteractionType(@InteractionType int interactionType) {
         Preconditions.assertUIThread();
         if (mInteractionType != INTERACTION_NORMAL) {
@@ -454,7 +474,10 @@
             // TODO: These should be done as part of ActivityOptions#OnAnimationStarted
             mLauncher.getStateManager().reapplyState();
             mLauncher.setOnResumeCallback(() -> mLauncherLayoutListener.close(false));
-            mLauncherTransitionController.setPlayFraction(1);
+
+            if (mLauncherTransitionController != null) {
+                mLauncherTransitionController.setPlayFraction(1);
+            }
         }
         clearReference();
     }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7595793..639fb6c 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -419,7 +419,11 @@
             getStateManager().reapplyState();
 
             // TODO: We can probably avoid rebind when only screen size changed.
-            mModel.startLoader(mWorkspace.getNextPage());
+            int currentPage = mWorkspace.getNextPage();
+            if (mModel.startLoader(currentPage)) {
+                mWorkspace.setCurrentPage(currentPage);
+                setWorkspaceLoading(true);
+            }
         }
 
         mOldConfig.setTo(newConfig);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index ad94a6b..0ebae81 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -184,6 +184,9 @@
     protected final Rect mInsets = new Rect();
     protected final boolean mIsRtl;
 
+    // Similar to the platform implementation of isLayoutValid();
+    protected boolean mIsLayoutValid;
+
     public PagedView(Context context) {
         this(context, null);
     }
@@ -582,6 +585,18 @@
     }
 
     @Override
+    public void requestLayout() {
+        mIsLayoutValid = false;
+        super.requestLayout();
+    }
+
+    @Override
+    public void forceLayout() {
+        mIsLayoutValid = false;
+        super.forceLayout();
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if (getChildCount() == 0) {
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -624,6 +639,7 @@
     @SuppressLint("DrawAllocation")
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        mIsLayoutValid = true;
         if (getChildCount() == 0) {
             return;
         }
@@ -640,8 +656,10 @@
         int scrollOffsetLeft = mInsets.left + getPaddingLeft();
         int childLeft = scrollOffsetLeft;
 
+        boolean pageScrollChanged = false;
         if (mPageScrolls == null || childCount != mChildCountOnLastLayout) {
             mPageScrolls = new int[childCount];
+            pageScrollChanged = true;
         }
 
         for (int i = startIndex; i != endIndex; i += delta) {
@@ -658,7 +676,11 @@
                 child.layout(childLeft, childTop,
                         childLeft + child.getMeasuredWidth(), childTop + childHeight);
 
-                mPageScrolls[i] = childLeft - scrollOffsetLeft;
+                final int pageScroll = childLeft - scrollOffsetLeft;
+                if (mPageScrolls[i] != pageScroll) {
+                    pageScrollChanged = true;
+                    mPageScrolls[i] = pageScroll;
+                }
 
                 childLeft += childWidth + mPageSpacing + getChildGap();
             }
@@ -693,7 +715,7 @@
             mFirstLayout = false;
         }
 
-        if (mScroller.isFinished() && mChildCountOnLastLayout != childCount) {
+        if (mScroller.isFinished() && pageScrollChanged) {
             setCurrentPage(getNextPage());
         }
         mChildCountOnLastLayout = childCount;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index e6aa6be..8fb0e1c 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -22,7 +22,6 @@
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
-import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -48,7 +47,6 @@
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Property;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -3354,13 +3352,13 @@
 
     @Override
     public int getExpectedHeight() {
-        return getMeasuredHeight() <= 0
+        return getMeasuredHeight() <= 0 || !mIsLayoutValid
                 ? mLauncher.getDeviceProfile().heightPx : getMeasuredHeight();
     }
 
     @Override
     public int getExpectedWidth() {
-        return getMeasuredWidth() <= 0
+        return getMeasuredWidth() <= 0 || !mIsLayoutValid
                 ? mLauncher.getDeviceProfile().widthPx : getMeasuredWidth();
     }