Snap for 7636897 from 7d87779debe34cf4d7aaa9e51d6c2dbfd8f796f2 to sc-v2-release

Change-Id: Icd1bcd77369ac673065e5308bfdf97172905a657
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 2009cd7..069af96 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -36,9 +36,13 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
+import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
 import android.view.HapticFeedbackConstants;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.BaseQuickstepLauncher;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
@@ -75,9 +79,14 @@
 import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskUtils;
+import com.android.quickstep.util.LauncherUnfoldAnimationController;
+import com.android.quickstep.util.ProxyScreenStatusProvider;
 import com.android.quickstep.util.QuickstepOnboardingPrefs;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
+import com.android.unfold.UnfoldTransitionFactory;
+import com.android.unfold.UnfoldTransitionProgressProvider;
+import com.android.unfold.config.UnfoldTransitionConfig;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -97,10 +106,51 @@
     private FixedContainerItems mAllAppsPredictions;
     private HotseatPredictionController mHotseatPredictionController;
 
+    @Nullable
+    private LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
+
     @Override
     protected void setupViews() {
         super.setupViews();
         mHotseatPredictionController = new HotseatPredictionController(this);
+
+        final UnfoldTransitionConfig config = UnfoldTransitionFactory.createConfig(this);
+        if (config.isEnabled()) {
+            final UnfoldTransitionProgressProvider unfoldTransitionProgressProvider =
+                    UnfoldTransitionFactory.createUnfoldTransitionProgressProvider(
+                            this,
+                            config,
+                            ProxyScreenStatusProvider.INSTANCE,
+                            getSystemService(DeviceStateManager.class),
+                            getSystemService(SensorManager.class),
+                            getMainThreadHandler(),
+                            getMainExecutor()
+                    );
+
+            mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
+                    this,
+                    getWindowManager(),
+                    unfoldTransitionProgressProvider
+            );
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        if (mLauncherUnfoldAnimationController != null) {
+            mLauncherUnfoldAnimationController.onResume();
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        if (mLauncherUnfoldAnimationController != null) {
+            mLauncherUnfoldAnimationController.onPause();
+        }
+
+        super.onPause();
     }
 
     @Override
@@ -231,6 +281,10 @@
     public void onDestroy() {
         super.onDestroy();
         mHotseatPredictionController.destroy();
+
+        if (mLauncherUnfoldAnimationController != null) {
+            mLauncherUnfoldAnimationController.onDestroy();
+        }
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 61622ee..4979206 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -100,6 +100,7 @@
 import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.util.AssistantUtilities;
 import com.android.quickstep.util.ProtoTracer;
+import com.android.quickstep.util.ProxyScreenStatusProvider;
 import com.android.quickstep.util.SplitScreenBounds;
 import com.android.systemui.plugins.OverscrollPlugin;
 import com.android.systemui.plugins.PluginListener;
@@ -268,6 +269,12 @@
             MAIN_EXECUTOR.execute(() -> SplitScreenBounds.INSTANCE.setSecondaryWindowBounds(wb));
         }
 
+        @BinderThread
+        @Override
+        public void onScreenTurnedOn() {
+            MAIN_EXECUTOR.execute(ProxyScreenStatusProvider.INSTANCE::onScreenTurnedOn);
+        }
+
         @Override
         public void onRotationProposal(int rotation, boolean isValid) {
             executeForTaskbarManager(() -> mTaskbarManager.onRotationProposal(rotation, isValid));
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
new file mode 100644
index 0000000..ea1ece8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+
+import com.android.launcher3.Launcher;
+import com.android.unfold.UnfoldTransitionProgressProvider;
+import com.android.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+
+/**
+ * Controls animations that are happening during unfolding foldable devices
+ */
+public class LauncherUnfoldAnimationController {
+
+    private final Launcher mLauncher;
+    private final UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
+    private final UnfoldMoveFromCenterWorkspaceAnimator mMoveFromCenterWorkspaceAnimation;
+
+    private final AnimationListener mAnimationListener = new AnimationListener();
+
+    private boolean mIsTransitionRunning = false;
+    private boolean mIsReadyToPlayAnimation = false;
+
+    public LauncherUnfoldAnimationController(
+            Launcher launcher,
+            WindowManager windowManager,
+            UnfoldTransitionProgressProvider unfoldTransitionProgressProvider) {
+        mLauncher = launcher;
+        mUnfoldTransitionProgressProvider = unfoldTransitionProgressProvider;
+        mMoveFromCenterWorkspaceAnimation = new UnfoldMoveFromCenterWorkspaceAnimator(launcher,
+                windowManager);
+        mUnfoldTransitionProgressProvider.addCallback(mAnimationListener);
+    }
+
+    /**
+     * Called when launcher is resumed
+     */
+    public void onResume() {
+        final ViewTreeObserver obs = mLauncher.getWorkspace().getViewTreeObserver();
+        obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            @Override
+            public boolean onPreDraw() {
+                if (obs.isAlive()) {
+                    onPreDrawAfterResume();
+                    obs.removeOnPreDrawListener(this);
+                }
+                return true;
+            }
+        });
+    }
+
+    /**
+     * Called when launcher activity is paused
+     */
+    public void onPause() {
+        mIsReadyToPlayAnimation = false;
+
+        if (mIsTransitionRunning) {
+            mIsTransitionRunning = false;
+            mMoveFromCenterWorkspaceAnimation.onTransitionFinished();
+        }
+    }
+
+    /**
+     * Called when launcher activity is destroyed
+     */
+    public void onDestroy() {
+        mUnfoldTransitionProgressProvider.removeCallback(mAnimationListener);
+    }
+
+    /**
+     * Called after performing layouting of the views after configuration change
+     */
+    private void onPreDrawAfterResume() {
+        mIsReadyToPlayAnimation = true;
+
+        if (mIsTransitionRunning) {
+            mMoveFromCenterWorkspaceAnimation.onTransitionStarted();
+        }
+    }
+
+    private class AnimationListener implements TransitionProgressListener {
+
+        @Override
+        public void onTransitionStarted() {
+            mIsTransitionRunning = true;
+
+            if (mIsReadyToPlayAnimation) {
+                mMoveFromCenterWorkspaceAnimation.onTransitionStarted();
+            }
+        }
+
+        @Override
+        public void onTransitionFinished() {
+            if (mIsReadyToPlayAnimation) {
+                mMoveFromCenterWorkspaceAnimation.onTransitionFinished();
+            }
+
+            mIsTransitionRunning = false;
+        }
+
+        @Override
+        public void onTransitionProgress(float progress) {
+            mMoveFromCenterWorkspaceAnimation.onTransitionProgress(progress);
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 65be624..b83e26e 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -17,7 +17,6 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 
@@ -86,12 +85,7 @@
         mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
         mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
         mForcePauseTimeout = new Alarm();
-        mForcePauseTimeout.setOnAlarmListener(alarm -> {
-            if (TestProtocol.sDebugTracing) {
-                Log.d(TestProtocol.MOTION_PAUSE_TIMEOUT, "onAlarm");
-            }
-            updatePaused(true /* isPaused */);
-        });
+        mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
         mMakePauseHarderToTrigger = makePauseHarderToTrigger;
         mVelocityProvider = new SystemVelocityProvider(axis);
     }
@@ -128,9 +122,6 @@
         long timeoutMs = TestProtocol.sForcePauseTimeout != null
                 ? TestProtocol.sForcePauseTimeout
                 : mMakePauseHarderToTrigger ? HARDER_TRIGGER_TIMEOUT : FORCE_PAUSE_TIMEOUT;
-        if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.MOTION_PAUSE_TIMEOUT, "setAlarm: " + timeoutMs);
-        }
         mForcePauseTimeout.setAlarm(timeoutMs);
         float newVelocity = mVelocityProvider.addMotionEvent(ev, ev.getPointerId(pointerIndex));
         if (mPreviousVelocity != null) {
@@ -172,9 +163,6 @@
                 }
             }
         }
-        if (TestProtocol.sDebugTracing) {
-            Log.d(TestProtocol.MOTION_PAUSE_TIMEOUT, "checkMotionPaused: " + isPaused);
-        }
         updatePaused(isPaused);
     }
 
diff --git a/quickstep/src/com/android/quickstep/util/ProxyScreenStatusProvider.java b/quickstep/src/com/android/quickstep/util/ProxyScreenStatusProvider.java
new file mode 100644
index 0000000..9eda8f4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/ProxyScreenStatusProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import androidx.annotation.NonNull;
+
+import com.android.unfold.updates.screen.ScreenStatusProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Screen status provider implementation that exposes methods to provide screen
+ * status updates to listeners. It is used to receive screen turned on event from
+ * SystemUI to Launcher.
+ */
+public class ProxyScreenStatusProvider implements ScreenStatusProvider {
+
+    public static final ProxyScreenStatusProvider INSTANCE = new ProxyScreenStatusProvider();
+    private final List<ScreenListener> mListeners = new ArrayList<>();
+
+    /**
+     * Called when the screen is on and ready (windows are drawn and screen blocker is removed)
+     */
+    public void onScreenTurnedOn() {
+        mListeners.forEach(ScreenListener::onScreenTurnedOn);
+    }
+
+    @Override
+    public void addCallback(@NonNull ScreenListener listener) {
+        mListeners.add(listener);
+    }
+
+    @Override
+    public void removeCallback(@NonNull ScreenListener listener) {
+        mListeners.remove(listener);
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
new file mode 100644
index 0000000..126e044
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import android.annotation.NonNull;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.Hotseat;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.ShortcutAndWidgetContainer;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.widget.NavigableAppWidgetHostView;
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.TranslationApplier;
+import com.android.unfold.UnfoldTransitionProgressProvider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Animation that moves launcher icons and widgets from center to the sides (final position)
+ */
+public class UnfoldMoveFromCenterWorkspaceAnimator
+        implements UnfoldTransitionProgressProvider.TransitionProgressListener {
+
+    private final Launcher mLauncher;
+    private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimation;
+
+    private final Map<ViewGroup, Boolean> mOriginalClipToPadding = new HashMap<>();
+    private final Map<ViewGroup, Boolean> mOriginalClipChildren = new HashMap<>();
+
+    public UnfoldMoveFromCenterWorkspaceAnimator(Launcher launcher, WindowManager windowManager) {
+        mLauncher = launcher;
+        mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
+                new WorkspaceViewsTranslationApplier());
+    }
+
+    @Override
+    public void onTransitionStarted() {
+        mMoveFromCenterAnimation.updateDisplayProperties();
+
+        Workspace workspace = mLauncher.getWorkspace();
+        Hotseat hotseat = mLauncher.getHotseat();
+
+        // App icons and widgets
+        workspace
+                .forEachVisiblePage(page -> {
+                    final CellLayout cellLayout = (CellLayout) page;
+                    ShortcutAndWidgetContainer itemsContainer = cellLayout
+                            .getShortcutsAndWidgets();
+                    disableClipping(cellLayout);
+
+                    for (int i = 0; i < itemsContainer.getChildCount(); i++) {
+                        View child = itemsContainer.getChildAt(i);
+                        mMoveFromCenterAnimation.registerViewForAnimation(child);
+                    }
+                });
+
+        disableClipping(workspace);
+
+        // Hotseat icons
+        ViewGroup hotseatIcons = hotseat.getShortcutsAndWidgets();
+        disableClipping(hotseat);
+
+        for (int i = 0; i < hotseatIcons.getChildCount(); i++) {
+            View child = hotseatIcons.getChildAt(i);
+            mMoveFromCenterAnimation.registerViewForAnimation(child);
+        }
+
+        onTransitionProgress(0f);
+    }
+
+    @Override
+    public void onTransitionProgress(float progress) {
+        mMoveFromCenterAnimation.onTransitionProgress(progress);
+    }
+
+    @Override
+    public void onTransitionFinished() {
+        mMoveFromCenterAnimation.onTransitionFinished();
+        mMoveFromCenterAnimation.clearRegisteredViews();
+
+        restoreClipping(mLauncher.getWorkspace());
+        mLauncher.getWorkspace().forEachVisiblePage(page -> restoreClipping((CellLayout) page));
+        restoreClipping(mLauncher.getHotseat());
+
+        mOriginalClipChildren.clear();
+        mOriginalClipToPadding.clear();
+    }
+
+    private void disableClipping(ViewGroup view) {
+        mOriginalClipToPadding.put(view, view.getClipToPadding());
+        mOriginalClipChildren.put(view, view.getClipChildren());
+        view.setClipToPadding(false);
+        view.setClipChildren(false);
+    }
+
+    private void restoreClipping(ViewGroup view) {
+        final Boolean originalClipToPadding = mOriginalClipToPadding.get(view);
+        if (originalClipToPadding != null) {
+            view.setClipToPadding(originalClipToPadding);
+        }
+        final Boolean originalClipChildren = mOriginalClipChildren.get(view);
+        if (originalClipChildren != null) {
+            view.setClipChildren(originalClipChildren);
+        }
+    }
+
+    private static class WorkspaceViewsTranslationApplier implements TranslationApplier {
+
+        @Override
+        public void apply(@NonNull View view, float x, float y) {
+            if (view instanceof NavigableAppWidgetHostView) {
+                ((NavigableAppWidgetHostView) view).setTranslationForMoveFromCenterAnimation(x, y);
+            } else if (view instanceof BubbleTextView) {
+                ((BubbleTextView) view).setTranslationForMoveFromCenterAnimation(x, y);
+            } else {
+                view.setTranslationX(x);
+                view.setTranslationY(y);
+            }
+        }
+    }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 164e755..e5e560a 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -37,7 +37,6 @@
 import com.android.launcher3.tapl.OverviewActions;
 import com.android.launcher3.tapl.OverviewTask;
 import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
 import com.android.quickstep.views.RecentsView;
 
@@ -158,7 +157,6 @@
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
-    @ScreenRecord //b/193125090
     public void testOverviewActions() throws Exception {
         // Experimenting for b/165029151:
         final Overview overview = mLauncher.pressHome().switchToOverview();
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 02fe7d9..353e52b 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -90,6 +90,8 @@
     private final PointF mTranslationForReorderBounce = new PointF(0, 0);
     private final PointF mTranslationForReorderPreview = new PointF(0, 0);
 
+    private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
+
     private float mScaleForReorderBounce = 1f;
 
     private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
@@ -800,8 +802,10 @@
     }
 
     private void updateTranslation() {
-        super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x);
-        super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y);
+        super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x
+                + mTranslationForMoveFromCenterAnimation.x);
+        super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
+                + mTranslationForMoveFromCenterAnimation.y);
     }
 
     public void setReorderBounceOffset(float x, float y) {
@@ -834,6 +838,11 @@
         return mScaleForReorderBounce;
     }
 
+    public void setTranslationForMoveFromCenterAnimation(float x, float y) {
+        mTranslationForMoveFromCenterAnimation.set(x, y);
+        updateTranslation();
+    }
+
     public View getView() {
         return this;
     }
diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java
index 6cdd3ca..103b565 100644
--- a/src/com/android/launcher3/testing/TestLogging.java
+++ b/src/com/android/launcher3/testing/TestLogging.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.testing;
 
 import android.util.Log;
+import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
@@ -48,17 +49,24 @@
         }
     }
 
+    private static void registerEventNotFromTest(InputEvent event) {
+        if (!sHadEventsNotFromTest && event.getDeviceId() != -1) {
+            sHadEventsNotFromTest = true;
+            Log.d(TestProtocol.PERMANENT_DIAG_TAG, "First event not from test: " + event);
+        }
+    }
+
     public static void recordKeyEvent(String sequence, String message, KeyEvent event) {
         if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
             recordEventSlow(sequence, message + ": " + event);
-            if (event.getDeviceId() != -1) sHadEventsNotFromTest = true;
+            registerEventNotFromTest(event);
         }
     }
 
     public static void recordMotionEvent(String sequence, String message, MotionEvent event) {
         if (Utilities.IS_RUNNING_IN_TEST_HARNESS && event.getAction() != MotionEvent.ACTION_MOVE) {
             recordEventSlow(sequence, message + ": " + event);
-            if (event.getDeviceId() != -1) sHadEventsNotFromTest = true;
+            registerEventNotFromTest(event);
         }
     }
 
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 38cbbe7..1c5b31b 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -118,6 +118,5 @@
     public static final String WORK_PROFILE_REMOVED = "b/159671700";
     public static final String FALLBACK_ACTIVITY_NO_SET = "b/181019015";
     public static final String THIRD_PARTY_LAUNCHER_NOT_SET = "b/187080582";
-    public static final String MOTION_PAUSE_TIMEOUT = "b/194114179";
     public static final String TASK_VIEW_ID_CRASH = "b/195430732";
 }
diff --git a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
index d12fe74..241c937 100644
--- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
@@ -49,6 +49,8 @@
      */
     private final PointF mTranslationForCentering = new PointF(0, 0);
 
+    private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
+
     private final PointF mTranslationForReorderBounce = new PointF(0, 0);
     private final PointF mTranslationForReorderPreview = new PointF(0, 0);
     private float mScaleForReorderBounce = 1f;
@@ -167,9 +169,9 @@
 
     private void updateTranslation() {
         super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x
-                + mTranslationForCentering.x);
+                + mTranslationForCentering.x + mTranslationForMoveFromCenterAnimation.x);
         super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
-                + mTranslationForCentering.y);
+                + mTranslationForCentering.y + mTranslationForMoveFromCenterAnimation.y);
     }
 
     public void setTranslationForCentering(float x, float y) {
@@ -177,6 +179,11 @@
         updateTranslation();
     }
 
+    public void setTranslationForMoveFromCenterAnimation(float x, float y) {
+        mTranslationForMoveFromCenterAnimation.set(x, y);
+        updateTranslation();
+    }
+
     public void setReorderBounceOffset(float x, float y) {
         mTranslationForReorderBounce.set(x, y);
         updateTranslation();
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index d3a0190..57a6d3f 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -85,7 +85,7 @@
         setBackgroundResource(R.drawable.pending_widget_bg);
         setWillNotDraw(false);
 
-        updateAppWidget(null);
+        super.updateAppWidget(null);
         setOnClickListener(ItemClickHandler.INSTANCE);
 
         if (info.pendingItemInfo == null) {
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index a8ed154..bd444db 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -483,6 +483,20 @@
         mAppWidgetHostViewPreview.measure(
                 makeMeasureSpec(MAX_MEASURE_SPEC_DIMENSION, MeasureSpec.UNSPECIFIED),
                 makeMeasureSpec(MAX_MEASURE_SPEC_DIMENSION, MeasureSpec.UNSPECIFIED));
+        if (mRemoteViewsPreview != null) {
+            // If RemoteViews contains multiple sizes, the best fit sized RemoteViews will be
+            // selected in onLayout. To work out the right measurement, let's layout and then
+            // measure again.
+            mAppWidgetHostViewPreview.layout(
+                    /* left= */ 0,
+                    /* top= */ 0,
+                    /* right= */ mTargetPreviewWidth,
+                    /* bottom= */ mTargetPreviewHeight);
+            mAppWidgetHostViewPreview.measure(
+                    makeMeasureSpec(mTargetPreviewWidth, MeasureSpec.UNSPECIFIED),
+                    makeMeasureSpec(mTargetPreviewHeight, MeasureSpec.UNSPECIFIED));
+
+        }
         View widgetContent = mAppWidgetHostViewPreview.getChildAt(0);
         int appWidgetContentWidth = widgetContent.getMeasuredWidth();
         int appWidgetContentHeight = widgetContent.getMeasuredHeight();
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 2e8048a..dad4f2b 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -27,7 +27,6 @@
 import com.android.launcher3.tapl.Widget;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.TestViewHelpers;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.util.rule.ShellCommandRule;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
@@ -81,7 +80,6 @@
      */
     @Test
     @PortraitLandscape
-    @ScreenRecord //b/195263971
     public void testDragCustomShortcut() throws Throwable {
         clearHomescreen();
         mDevice.pressHome();
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index ded4282..065af00 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -66,7 +66,6 @@
 
 import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.testing.TestProtocol;
-import com.android.systemui.shared.system.ContextUtils;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import org.junit.Assert;
@@ -80,6 +79,7 @@
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -96,7 +96,7 @@
     private static final String TAG = "Tapl";
     private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 20;
     private static final int GESTURE_STEP_MS = 16;
-    private static final long FORCE_PAUSE_TIMEOUT_MS = 700;
+    private static final long FORCE_PAUSE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2);
 
     static final Pattern EVENT_TOUCH_DOWN = getTouchEventPattern("ACTION_DOWN");
     static final Pattern EVENT_TOUCH_UP = getTouchEventPattern("ACTION_UP");
@@ -245,16 +245,12 @@
         ComponentName cn = new ComponentName(pi.packageName, pi.name);
 
         if (pm.getComponentEnabledSetting(cn) != COMPONENT_ENABLED_STATE_ENABLED) {
-            if (TestHelpers.isInLauncherProcess()) {
+            mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                    android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+            try {
                 pm.setComponentEnabledSetting(cn, COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
-            } else {
-                try {
-                    final int userId = ContextUtils.getUserId(getContext());
-                    mDevice.executeShellCommand(
-                            "pm enable --user " + userId + " " + cn.flattenToString());
-                } catch (IOException e) {
-                    fail(e.toString());
-                }
+            } finally {
+                mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
             }
         }
     }
@@ -304,7 +300,7 @@
 
     public boolean isTwoPanels() {
         return getTestInfo(TestProtocol.REQUEST_IS_TWO_PANELS)
-            .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+                .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
     private void setForcePauseTimeout(long timeout) {