Merge cherrypicks of [7773042, 7773101, 7772813, 7772985, 7772987, 7772989] into qt-c2f2-release

Change-Id: Iaf1c2438d66b8a68b4f2860d6b07ab4f4243f8db
diff --git a/Android.bp b/Android.bp
index b80282e..4c38205 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,7 +25,7 @@
         "tests/tapl/**/*.java",
         "src/com/android/launcher3/util/SecureSettingsObserver.java",
         "src/com/android/launcher3/ResourceUtils.java",
-        "src/com/android/launcher3/TestProtocol.java",
+        "src/com/android/launcher3/testing/TestProtocol.java",
     ],
     manifest: "tests/tapl/AndroidManifest.xml",
     platform_apis: true,
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index ef5bb26..5318a12 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -176,5 +176,12 @@
             </intent-filter>
         </activity>
 
+        <provider
+            android:name="com.android.launcher3.testing.TestInformationProvider"
+            android:authorities="${packageName}.TestInfo"
+            android:readPermission="android.permission.WRITE_SECURE_SETTINGS"
+            android:writePermission="android.permission.WRITE_SECURE_SETTINGS"
+            android:exported="true"
+            android:enabled="false" />
     </application>
 </manifest>
diff --git a/OWNERS b/OWNERS
index 98dfb8a..8b3df48 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,13 +2,11 @@
 # gnl-eng@google.com (Googlers only)
 
 # People who can approve changes for submission
+#
+
 adamcohen@google.com
 hyunyoungs@google.com
+mrcasey@google.com
 sunnygoyal@google.com
-winsonc@google.com
-
-# Source of truth of this directory is actually in launcher team's
-# unbundled branch ub-launcher3-[release variant] (e.g., master, edmonton).
-# Pls try to wait for one of the owner's review if you have to force
-# submit (e.g., for large refactor, breakage, etc) as we may want to
-# cherry pick the change to our active developmental branch.
+twickham@google.com
+winsonc@google.com
\ No newline at end of file
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index be275e0..a38979d 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -73,14 +73,6 @@
             </intent-filter>
         </provider>
 
-        <provider
-            android:name="com.android.quickstep.TestInformationProvider"
-            android:authorities="${packageName}.TestInfo"
-            android:readPermission="android.permission.WRITE_SECURE_SETTINGS"
-            android:writePermission="android.permission.WRITE_SECURE_SETTINGS"
-            android:exported="true">
-        </provider>
-
         <service
             android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
             tools:node="remove" />
diff --git a/quickstep/recents_ui_overrides/res/layout/prediction_load_progress.xml b/quickstep/recents_ui_overrides/res/layout/prediction_load_progress.xml
deleted file mode 100644
index 20c4004..0000000
--- a/quickstep/recents_ui_overrides/res/layout/prediction_load_progress.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
-    style="?android:attr/progressBarStyleHorizontal"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:layout_marginLeft="20dp"
-    android:layout_marginRight="20dp"
-    android:indeterminate="true"
-    android:indeterminateOnly="true"
-    android:indeterminateTint="?workspaceTextColor" />
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
index af67e1b..8f1282d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
@@ -56,7 +56,7 @@
     private static final int MSG_LAUNCH = 2;
     private static final int MSG_PREDICT = 3;
 
-    private final Context mContext;
+    protected final Context mContext;
     private final Handler mMessageHandler;
 
     // Accessed only on worker thread
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
index 55f4c98..4a486f8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -28,7 +28,6 @@
 import android.util.AttributeSet;
 import android.util.IntProperty;
 import android.util.Log;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.animation.Interpolator;
 import android.widget.LinearLayout;
@@ -115,8 +114,6 @@
     private final AnimatedFloat mOverviewScrollFactor =
             new AnimatedFloat(this::updateTranslationAndAlpha);
 
-    private View mLoadingProgress;
-
     private boolean mPredictionsEnabled = false;
 
     public PredictionRowView(@NonNull Context context) {
@@ -165,7 +162,6 @@
 
     public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
         mParent = parent;
-        setPredictionsEnabled(mPredictionUiStateManager.arePredictionsEnabled());
     }
 
     private void setPredictionsEnabled(boolean predictionsEnabled) {
@@ -205,7 +201,7 @@
 
     @Override
     public boolean hasVisibleContent() {
-        return mPredictionUiStateManager.arePredictionsEnabled();
+        return mPredictionsEnabled;
     }
 
     /**
@@ -241,9 +237,6 @@
     }
 
     private void applyPredictionApps() {
-        if (mLoadingProgress != null) {
-            removeView(mLoadingProgress);
-        }
         if (!mPredictionsEnabled) {
             mParent.onHeightUpdated();
             return;
@@ -290,15 +283,8 @@
         }
 
         if (predictionCount == 0) {
-            if (mLoadingProgress == null) {
-                mLoadingProgress = LayoutInflater.from(getContext())
-                        .inflate(R.layout.prediction_load_progress, this, false);
-            }
-            addView(mLoadingProgress);
-        } else {
-            mLoadingProgress = null;
+            setPredictionsEnabled(false);
         }
-
         mParent.onHeightUpdated();
     }
 
@@ -342,11 +328,8 @@
     public void setTextAlpha(int alpha) {
         mIconCurrentTextAlpha = alpha;
         int iconColor = setColorAlphaBound(mIconTextColor, mIconCurrentTextAlpha);
-
-        if (mLoadingProgress == null) {
-            for (int i = 0; i < getChildCount(); i++) {
-                ((BubbleTextView) getChildAt(i)).setTextColor(iconColor);
-            }
+        for (int i = 0; i < getChildCount(); i++) {
+            ((BubbleTextView) getChildAt(i)).setTextColor(iconColor);
         }
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 6dad9af..64cb4b4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -24,7 +24,6 @@
 import android.app.prediction.AppTarget;
 import android.content.ComponentName;
 import android.content.Context;
-import android.os.Handler;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 
 import com.android.launcher3.AppInfo;
@@ -63,7 +62,6 @@
         OnIDPChangeListener, OnUpdateListener {
 
     public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
-    private static final long INITIAL_CALLBACK_WAIT_TIMEOUT_MS = 5000;
 
     // TODO (b/129421797): Update the client constants
     public enum Client {
@@ -110,13 +108,8 @@
         for (int i = 0; i < mPredictionServicePredictions.length; i++) {
             mPredictionServicePredictions[i] = Collections.emptyList();
         }
-
         mGettingValidPredictionResults = Utilities.getDevicePrefs(context)
                 .getBoolean(LAST_PREDICTION_ENABLED_STATE, true);
-        if (mGettingValidPredictionResults) {
-            new Handler().postDelayed(
-                    this::updatePredictionStateAfterCallback, INITIAL_CALLBACK_WAIT_TIMEOUT_MS);
-        }
 
         // Call this last
         mCurrentState = parseLastState();
@@ -293,10 +286,6 @@
         dispatchOnChange(false);
     }
 
-    public boolean arePredictionsEnabled() {
-        return mCurrentState.isEnabled;
-    }
-
     private boolean canApplyPredictions(PredictionState newState) {
         if (mAppsView == null) {
             // If there is no apps view, no need to schedule.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 0c997dd..6ba1bf5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -331,16 +331,8 @@
         defaultDisplay.getRealSize(realSize);
         mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
         if (mMode == Mode.NO_BUTTON) {
-            switch (defaultDisplay.getRotation()) {
-                case Surface.ROTATION_90:
-                case Surface.ROTATION_270:
-                    mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
-                            ResourceUtils.NAVBAR_LANDSCAPE_BOTTOM_SIZE);
-                    break;
-                default:
-                    mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
-                            ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE);
-            }
+            mSwipeTouchRegion.top = mSwipeTouchRegion.bottom -
+                    getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
         } else {
             switch (defaultDisplay.getRotation()) {
                 case Surface.ROTATION_90:
@@ -353,7 +345,7 @@
                     break;
                 default:
                     mSwipeTouchRegion.top = mSwipeTouchRegion.bottom
-                            - getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE);
+                            - getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
             }
         }
     }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 2ff5c0c..ffef1cf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -170,7 +170,8 @@
             STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
 
     public enum GestureEndTarget {
-        HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE, false),
+        HOME(1, STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT, true, false,
+                ContainerType.WORKSPACE, false),
 
         RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
                 | STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER, true),
@@ -331,9 +332,8 @@
                         | STATE_SCALED_CONTROLLER_RECENTS,
                 this::finishCurrentTransitionToRecents);
 
-        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_COMPLETED
-                        | STATE_SCALED_CONTROLLER_HOME | STATE_APP_CONTROLLER_RECEIVED
-                        | STATE_LAUNCHER_DRAWN,
+        mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
+                        | STATE_SCALED_CONTROLLER_HOME,
                 this::finishCurrentTransitionToHome);
         mStateCallback.addCallback(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED,
                 this::reset);
@@ -936,8 +936,10 @@
         } else if (endTarget == RECENTS) {
             mLiveTileOverlay.startIconAnimation();
             if (mRecentsView != null) {
-                duration = Utilities.boundToRange(mRecentsView.getScroller().getDuration(),
-                        duration, MAX_SWIPE_DURATION);
+                if (mRecentsView.getScroller().getDuration() > MAX_SWIPE_DURATION) {
+                    mRecentsView.snapToPage(mRecentsView.getNextPage(), (int) MAX_SWIPE_DURATION);
+                }
+                duration = Math.max(duration, mRecentsView.getScroller().getDuration());
             }
             if (mMode == Mode.NO_BUTTON) {
                 setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
@@ -1251,8 +1253,15 @@
                 if (mTaskSnapshot == null) {
                     mTaskSnapshot = controller.screenshotTask(mRunningTaskId);
                 }
-                TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
-                if (taskView != null) {
+                final TaskView taskView;
+                if (mGestureEndTarget == HOME) {
+                    // Capture the screenshot before finishing the transition to home to ensure it's
+                    // taken in the correct orientation, but no need to update the thumbnail.
+                    taskView = null;
+                } else {
+                    taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
+                }
+                if (taskView != null && !mCanceled) {
                     // Defer finishing the animation until the next launcher frame with the
                     // new thumbnail
                     finishTransitionPosted = new WindowCallbacksCompat(taskView) {
@@ -1262,6 +1271,13 @@
 
                         @Override
                         public void onPostDraw(Canvas canvas) {
+                            // If we were cancelled after this was attached, do not update
+                            // the state.
+                            if (mCanceled) {
+                                detach();
+                                return;
+                            }
+
                             if (mDeferFrameCount > 0) {
                                 mDeferFrameCount--;
                                 // Workaround, detach and reattach to invalidate the root node for
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
index 09d323e..1820729 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
@@ -20,7 +20,6 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.view.WindowInsets;
 
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.R;
@@ -71,7 +70,7 @@
         // Update device profile before notifying the children.
         mActivity.getDeviceProfile().updateInsets(insets);
         setInsets(insets);
-        return true; // I'll take it from here
+        return false; // Let children get the full insets
     }
 
     @Override
@@ -89,10 +88,4 @@
         mActivity.getDeviceProfile().updateInsets(mInsets);
         super.setInsets(mInsets);
     }
-
-    @Override
-    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
-        updateTouchExcludeRegion(insets);
-        return super.dispatchApplyWindowInsets(insets);
-    }
 }
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
index 3f4ad58..77dc6f3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -16,26 +16,22 @@
 package com.android.quickstep.util;
 
 import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
 import android.content.res.Resources;
 import android.graphics.PointF;
 import android.graphics.RectF;
-import android.util.FloatProperty;
 
 import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener;
 import androidx.dynamicanimation.animation.FloatPropertyCompat;
+import androidx.dynamicanimation.animation.SpringAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.FlingSpringAnim;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
 
 /**
  * Applies spring forces to animate from a starting rect to a target rect,
@@ -43,14 +39,6 @@
  */
 public class RectFSpringAnim {
 
-    /**
-     * Although the rect position animation takes an indefinite amount of time since it depends on
-     * the initial velocity and applied forces, scaling from the starting rect to the target rect
-     * can be done in parallel at a fixed duration. Update callbacks are sent based on the progress
-     * of this animation, while the end callback is sent after all animations finish.
-     */
-    private static final long RECT_SCALE_DURATION = 250;
-
     private static final FloatPropertyCompat<RectFSpringAnim> RECT_CENTER_X =
             new FloatPropertyCompat<RectFSpringAnim>("rectCenterXSpring") {
                 @Override
@@ -79,17 +67,17 @@
                 }
             };
 
-    private static final FloatProperty<RectFSpringAnim> RECT_SCALE_PROGRESS =
-            new FloatProperty<RectFSpringAnim>("rectScaleProgress") {
+    private static final FloatPropertyCompat<RectFSpringAnim> RECT_SCALE_PROGRESS =
+            new FloatPropertyCompat<RectFSpringAnim>("rectScaleProgress") {
                 @Override
-                public Float get(RectFSpringAnim anim) {
-                    return anim.mCurrentScaleProgress;
+                public float getValue(RectFSpringAnim object) {
+                    return object.mCurrentScaleProgress;
                 }
 
                 @Override
-                public void setValue(RectFSpringAnim anim, float currentScaleProgress) {
-                    anim.mCurrentScaleProgress = currentScaleProgress;
-                    anim.onUpdate();
+                public void setValue(RectFSpringAnim object, float value) {
+                    object.mCurrentScaleProgress = value;
+                    object.onUpdate();
                 }
             };
 
@@ -106,7 +94,7 @@
     private float mCurrentScaleProgress;
     private FlingSpringAnim mRectXAnim;
     private FlingSpringAnim mRectYAnim;
-    private ValueAnimator mRectScaleAnim;
+    private SpringAnimation mRectScaleAnim;
     private boolean mAnimsStarted;
     private boolean mRectXAnimEnded;
     private boolean mRectYAnimEnded;
@@ -177,17 +165,18 @@
         mRectYAnim = new FlingSpringAnim(this, RECT_Y, startY, endY, startVelocityY,
                 mMinVisChange, minYValue, maxYValue, springVelocityFactor, onYEndListener);
 
-        mRectScaleAnim = ObjectAnimator.ofPropertyValuesHolder(this,
-                PropertyValuesHolder.ofFloat(RECT_SCALE_PROGRESS, 1))
-                .setDuration(RECT_SCALE_DURATION);
-        mRectScaleAnim.setInterpolator(DEACCEL);
-        mRectScaleAnim.addListener(new AnimationSuccessListener() {
-            @Override
-            public void onAnimationSuccess(Animator animator) {
-                mRectScaleAnimEnded = true;
-                maybeOnEnd();
-            }
-        });
+        float minVisibleChange = 1f / mStartRect.height();
+        mRectScaleAnim = new SpringAnimation(this, RECT_SCALE_PROGRESS)
+                .setSpring(new SpringForce(1f)
+                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+                .setStiffness(SpringForce.STIFFNESS_LOW))
+                .setStartVelocity(velocityPxPerMs.y * minVisibleChange)
+                .setMaxValue(1f)
+                .setMinimumVisibleChange(minVisibleChange)
+                .addEndListener((animation, canceled, value, velocity) -> {
+                    mRectScaleAnimEnded = true;
+                    maybeOnEnd();
+                });
 
         mRectXAnim.start();
         mRectYAnim.start();
@@ -202,7 +191,9 @@
         if (mAnimsStarted) {
             mRectXAnim.end();
             mRectYAnim.end();
-            mRectScaleAnim.end();
+            if (mRectScaleAnim.canSkipToEnd()) {
+                mRectScaleAnim.skipToEnd();
+            }
         }
     }
 
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index e84543b..5c4d6d8 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -25,6 +25,8 @@
 
     <string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
 
+    <string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
+
     <!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
          determines how many thumbnails will be fetched in the background. -->
     <integer name="recentsThumbnailCacheSize">3</integer>
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
new file mode 100644
index 0000000..8951363
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -0,0 +1,36 @@
+package com.android.quickstep;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.launcher3.testing.TestInformationHandler;
+import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.uioverrides.states.OverviewState;
+import com.android.quickstep.util.LayoutUtils;
+
+public class QuickstepTestInformationHandler extends TestInformationHandler {
+
+    public QuickstepTestInformationHandler(Context context) { }
+
+    @Override
+    public Bundle call(String method) {
+        final Bundle response = new Bundle();
+        switch (method) {
+            case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
+                final float swipeHeight =
+                        OverviewState.getDefaultSwipeHeight(mDeviceProfile);
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
+                return response;
+            }
+
+            case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
+                final float swipeHeight =
+                        LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
+                return response;
+            }
+        }
+
+        return super.call(method);
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/TestInformationProvider.java b/quickstep/src/com/android/quickstep/TestInformationProvider.java
deleted file mode 100644
index d96f9af..0000000
--- a/quickstep/src/com/android/quickstep/TestInformationProvider.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2019 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;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.TestProtocol;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.states.OverviewState;
-import com.android.quickstep.util.LayoutUtils;
-
-public class TestInformationProvider extends ContentProvider {
-    @Override
-    public boolean onCreate() {
-        return true;
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
-        return 0;
-    }
-
-    @Override
-    public int delete(Uri uri, String s, String[] strings) {
-        return 0;
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues contentValues) {
-        return null;
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        return null;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
-        return null;
-    }
-
-    @Override
-    public Bundle call(String method, String arg, Bundle extras) {
-        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
-            final Bundle response = new Bundle();
-            final Context context = getContext();
-            final DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.
-                    get(context).getDeviceProfile(context);
-            final LauncherAppState launcherAppState = LauncherAppState.getInstanceNoCreate();
-            final Launcher launcher = launcherAppState != null ?
-                    (Launcher) launcherAppState.getModel().getCallback() : null;
-
-            switch (method) {
-                case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
-                    final float swipeHeight =
-                            OverviewState.getDefaultSwipeHeight(deviceProfile);
-                    response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
-                    break;
-                }
-
-                case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
-                    final float swipeHeight =
-                            LayoutUtils.getShelfTrackingDistance(context, deviceProfile);
-                    response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
-                    break;
-                }
-
-                case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: {
-                    if (launcher == null) return null;
-
-                    final float progress = LauncherState.OVERVIEW.getVerticalProgress(launcher)
-                            - LauncherState.ALL_APPS.getVerticalProgress(launcher);
-                    final float distance =
-                            launcher.getAllAppsController().getShiftRange() * progress;
-                    response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
-                    break;
-                }
-
-                case TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT: {
-                    if (launcher == null) return null;
-
-                    final float progress = LauncherState.NORMAL.getVerticalProgress(launcher)
-                            - LauncherState.ALL_APPS.getVerticalProgress(launcher);
-                    final float distance =
-                            launcher.getAllAppsController().getShiftRange() * progress;
-                    response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
-                    break;
-                }
-
-                case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
-                    TestProtocol.sDebugTracing = true;
-                    break;
-
-                case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
-                    TestProtocol.sDebugTracing = false;
-                    break;
-            }
-            return response;
-        }
-        return null;
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 893c053..801a560 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -21,6 +21,7 @@
 
 import com.android.launcher3.Alarm;
 import com.android.launcher3.R;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
 
 /**
  * Given positions along x- or y-axis, tracks velocity and acceleration and determines when there is
@@ -47,6 +48,7 @@
     private final float mSpeedFast;
     private final Alarm mForcePauseTimeout;
     private final boolean mMakePauseHarderToTrigger;
+    private final Context mContext;
 
     private Long mPreviousTime = null;
     private Float mPreviousPosition = null;
@@ -71,6 +73,7 @@
      * @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
      */
     public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger) {
+        mContext = context;
         Resources res = context.getResources();
         mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
         mSpeedSlow = res.getDimension(R.dimen.motion_pause_detector_speed_slow);
@@ -165,6 +168,7 @@
         if (mIsPaused != isPaused) {
             mIsPaused = isPaused;
             if (mIsPaused) {
+                AccessibilityManagerCompat.sendPauseDetectedEventToTest(mContext);
                 mHasEverBeenPaused = true;
             }
             if (mOnMotionPauseListener != null) {
diff --git a/quickstep/tests/OWNERS b/quickstep/tests/OWNERS
new file mode 100644
index 0000000..046d871
--- /dev/null
+++ b/quickstep/tests/OWNERS
@@ -0,0 +1 @@
+vadimt@google.com
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index 5e20e56..d9fcf4d 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -68,7 +68,6 @@
 
         // Disable app tracker
         AppLaunchTracker.INSTANCE.initializeForTesting(new AppLaunchTracker());
-
         PredictionUiStateManager.INSTANCE.initializeForTesting(null);
 
         mCallback = PredictionUiStateManager.INSTANCE.get(mTargetContext).appPredictorCallback(
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 43d6311..f02859f 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -127,7 +127,7 @@
         assertNotNull("OverviewTask.open returned null", task.open());
         assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
                 By.pkg(getAppPackageName()).text("TestActivity2")),
-                LONG_WAIT_TIME_MS));
+                DEFAULT_UI_TIMEOUT));
         executeOnLauncher(launcher -> assertTrue(
                 "Launcher activity is the top activity; expecting another activity to be the top "
                         + "one",
diff --git a/res/values/config.xml b/res/values/config.xml
index 984729b..638a411 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -71,6 +71,7 @@
     <string name="main_process_initializer_class" translatable="false"></string>
     <string name="system_shortcut_factory_class" translatable="false"></string>
     <string name="app_launch_tracker_class" translatable="false"></string>
+    <string name="test_information_handler_class" translatable="false"></string>
 
     <!-- Package name of the default wallpaper picker. -->
     <string name="wallpaper_picker_package" translatable="false"></string>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index bd6ac90..f69b172 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -34,6 +34,7 @@
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.model.AppLaunchTracker;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.uioverrides.DisplayRotationListener;
 import com.android.launcher3.uioverrides.WallpaperColorInfo;
 import com.android.launcher3.util.Themes;
@@ -134,8 +135,8 @@
 
     public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
             @Nullable String sourceContainer) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_START_TAG,
                     "startActivitySafely 1");
         }
         if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
@@ -161,8 +162,8 @@
                 startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
             } else if (user == null || user.equals(Process.myUserHandle())) {
                 // Could be launching some bookkeeping activity
-                if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                    android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+                if (TestProtocol.sDebugTracing) {
+                    android.util.Log.d(TestProtocol.NO_START_TAG,
                             "startActivitySafely 2");
                 }
                 startActivity(intent, optsBundle);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a59189b..711cfd2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -29,6 +29,7 @@
 import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
 import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
 import static com.android.launcher3.logging.LoggerUtils.newTarget;
+import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
 import static com.android.launcher3.util.RaceConditionTracker.ENTER;
 import static com.android.launcher3.util.RaceConditionTracker.EXIT;
 
@@ -76,8 +77,6 @@
 import android.view.animation.OvershootInterpolator;
 import android.widget.Toast;
 
-import androidx.annotation.Nullable;
-
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.allapps.AllAppsContainerView;
@@ -110,6 +109,7 @@
 import com.android.launcher3.shortcuts.DeepShortcutManager;
 import com.android.launcher3.states.InternalStateHandler;
 import com.android.launcher3.states.RotationHelper;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -154,6 +154,8 @@
 import java.util.List;
 import java.util.function.Predicate;
 
+import androidx.annotation.Nullable;
+
 /**
  * Default launcher application.
  */
@@ -406,6 +408,7 @@
         super.onEnterAnimationComplete();
         UiFactory.onEnterAnimationComplete(this);
         mAllAppsController.highlightWorkTabIfNecessary();
+        mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
     }
 
     @Override
@@ -1782,8 +1785,8 @@
 
     public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
             @Nullable String sourceContainer) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_START_TAG,
                     "startActivitySafely outer");
         }
         boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 20eec05..49b380b 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -14,7 +14,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewDebug;
-import android.view.WindowInsets;
 
 import java.util.Collections;
 import java.util.List;
@@ -101,7 +100,7 @@
             mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
         }
 
-        return true; // I'll take it from here
+        return false; // Let children get the full insets
     }
 
     @Override
@@ -157,12 +156,6 @@
     }
 
     @Override
-    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
-        mLauncher.getDragLayer().updateTouchExcludeRegion(insets);
-        return super.dispatchApplyWindowInsets(insets);
-    }
-
-    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
         SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index eff58a7..3a92dfb 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -18,13 +18,13 @@
 import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
 import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
-import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
 import static com.android.launcher3.anim.Interpolators.ACCEL_2;
 import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
 
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 49ae338..3edd838 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -48,6 +48,7 @@
 import com.android.launcher3.anim.AnimatorSetBuilder;
 import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.uioverrides.UiFactory;
 
 import java.io.PrintWriter;
@@ -447,8 +448,8 @@
     }
 
     private void onStateTransitionStart(LauncherState state) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                     "onStateTransitionStart");
         }
         if (mState != state) {
@@ -576,8 +577,8 @@
         private final AnimatorSet mAnim;
 
         public StartAnimRunnable(AnimatorSet anim) {
-            if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+            if (TestProtocol.sDebugTracing) {
+                android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                         "StartAnimRunnable");
             }
             mAnim = anim;
diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java
index 0c80d13..73e705b 100644
--- a/src/com/android/launcher3/ResourceUtils.java
+++ b/src/com/android/launcher3/ResourceUtils.java
@@ -21,10 +21,9 @@
 import android.util.TypedValue;
 
 public class ResourceUtils {
-    public static final String NAVBAR_PORTRAIT_BOTTOM_SIZE = "navigation_bar_frame_height";
     public static final String NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE = "navigation_bar_width";
-    public static final String NAVBAR_LANDSCAPE_BOTTOM_SIZE
-            = "navigation_bar_frame_height_landscape";
+    public static final String NAVBAR_BOTTOM_GESTURE_SIZE = "navigation_bar_gesture_height";
+
 
     public static int getNavbarSize(String resName, Resources res) {
         return getDimenByName(resName, res, 48);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index d19f9cd..f784226 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -20,8 +20,6 @@
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
@@ -86,6 +84,7 @@
 import com.android.launcher3.pageindicators.WorkspacePageIndicator;
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.touch.WorkspaceTouchListener;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -371,8 +370,8 @@
 
     @Override
     public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                     "onDragStart 1");
         }
         if (ENFORCE_DRAG_EVENT_ORDER) {
@@ -425,8 +424,8 @@
         }
 
         // Always enter the spring loaded mode
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                     "onDragStart 2");
         }
         mLauncher.getStateManager().goToState(SPRING_LOADED);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 63682c7..053c570 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -31,6 +31,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
 
 import com.android.launcher3.AppInfo;
 import com.android.launcher3.DeviceProfile;
@@ -43,7 +44,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.config.FeatureFlags;
@@ -321,13 +322,22 @@
         }
         setLayoutParams(mlp);
 
-        mNavBarScrimHeight = insets.bottom;
         InsettableFrameLayout.dispatchInsets(this, insets);
         mLauncher.getAllAppsController()
                 .setScrollRangeDelta(mSearchUiManager.getScrollRangeDelta(insets));
     }
 
     @Override
+    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+        if (Utilities.ATLEAST_Q) {
+            mNavBarScrimHeight = insets.getTappableElementInsets().bottom;
+        } else {
+            mNavBarScrimHeight = insets.getStableInsetBottom();
+        }
+        return super.dispatchApplyWindowInsets(insets);
+    }
+
+    @Override
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
 
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 548d5de..a0e9dc5 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -425,7 +425,7 @@
     public void onScrollStateChanged(int state) {
         super.onScrollStateChanged(state);
 
-        if (state == SCROLL_STATE_IDLE && Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+        if (state == SCROLL_STATE_IDLE) {
             AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
         }
     }
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 86f773f..81c95cb 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -23,7 +23,7 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.Utilities;
 
 import java.util.function.Consumer;
@@ -69,6 +69,13 @@
         sendEventToTest(accessibilityManager, TestProtocol.SCROLL_FINISHED_MESSAGE, null);
     }
 
+    public static void sendPauseDetectedEventToTest(Context context) {
+        final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
+        if (accessibilityManager == null) return;
+
+        sendEventToTest(accessibilityManager, TestProtocol.PAUSE_DETECTED_MESSAGE, null);
+    }
+
     private static void sendEventToTest(
             AccessibilityManager accessibilityManager, String eventTag, Bundle data) {
         final AccessibilityEvent e = AccessibilityEvent.obtain(
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 7e20d11..54d0db1 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -105,7 +105,7 @@
             "ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview");
 
     public static final TogglableFlag ENABLE_HINTS_IN_OVERVIEW = new TogglableFlag(
-            "ENABLE_HINTS_IN_OVERVIEW", false,
+            "ENABLE_HINTS_IN_OVERVIEW", true,
             "Show chip hints and gleams on the overview screen");
 
     public static final TogglableFlag FAKE_LANDSCAPE_UI = new TogglableFlag(
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index bf692fe..9d3c8f7 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -41,6 +41,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.WorkspaceItemInfo;
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.util.TouchController;
@@ -472,8 +473,8 @@
     }
 
     private void handleMoveEvent(int x, int y) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                     "handleMoveEvent 1");
         }
         mDragObject.dragView.move(x, y);
@@ -492,8 +493,8 @@
 
         if (mIsInPreDrag && mOptions.preDragCondition != null
                 && mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) {
-            if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+            if (TestProtocol.sDebugTracing) {
+                android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                         "handleMoveEvent 2");
             }
             callOnDragStart();
@@ -533,8 +534,8 @@
      * Call this from a drag source view.
      */
     public boolean onControllerTouchEvent(MotionEvent ev) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                     "onControllerTouchEvent");
         }
         if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 9d46cf2..d1bd2db 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -44,6 +44,7 @@
 import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.LauncherStateManager;
@@ -54,7 +55,6 @@
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.Thunk;
-import com.android.launcher3.util.UiThreadHelper;
 
 import java.util.Arrays;
 
@@ -210,7 +210,7 @@
             return;
         }
         // Load the adaptive icon on a background thread and add the view in ui thread.
-        new Handler(UiThreadHelper.getBackgroundLooper()).postAtFrontOfQueue(new Runnable() {
+        new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(new Runnable() {
             @Override
             public void run() {
                 Object[] outObj = new Object[1];
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 3727fa6..b6c3c35 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -63,6 +63,10 @@
      */
     private int mStateHandlerRequest = REQUEST_NONE;
     /**
+     * Rotation request made by an app transition
+     */
+    private int mCurrentTransitionRequest = REQUEST_NONE;
+    /**
      * Rotation request made by a Launcher State
      */
     private int mCurrentStateRequest = REQUEST_NONE;
@@ -123,6 +127,13 @@
         }
     }
 
+    public void setCurrentTransitionRequest(int request) {
+        if (mCurrentTransitionRequest != request) {
+            mCurrentTransitionRequest = request;
+            notifyChange();
+        }
+    }
+
     public void setCurrentStateRequest(int request) {
         if (mCurrentStateRequest != request) {
             mCurrentStateRequest = request;
@@ -163,6 +174,9 @@
         if (mStateHandlerRequest != REQUEST_NONE) {
             activityFlags = mStateHandlerRequest == REQUEST_LOCK ?
                     SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
+        } else if (mCurrentTransitionRequest != REQUEST_NONE) {
+            activityFlags = mCurrentTransitionRequest == REQUEST_LOCK ?
+                    SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
         } else if (mCurrentStateRequest == REQUEST_LOCK) {
             activityFlags = SCREEN_ORIENTATION_LOCKED;
         } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
new file mode 100644
index 0000000..b8476aa
--- /dev/null
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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.launcher3.testing;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+public class TestInformationHandler implements ResourceBasedOverride {
+
+    public static TestInformationHandler newInstance(Context context) {
+        return Overrides.getObject(TestInformationHandler.class,
+                context, R.string.test_information_handler_class);
+    }
+
+    protected Context mContext;
+    protected DeviceProfile mDeviceProfile;
+    protected LauncherAppState mLauncherAppState;
+    protected Launcher mLauncher;
+
+    public void init(Context context) {
+        mContext = context;
+        mDeviceProfile = InvariantDeviceProfile.INSTANCE.
+                get(context).getDeviceProfile(context);
+        mLauncherAppState = LauncherAppState.getInstanceNoCreate();
+        mLauncher = mLauncherAppState != null ?
+                (Launcher) mLauncherAppState.getModel().getCallback() : null;
+    }
+
+    public Bundle call(String method) {
+        final Bundle response = new Bundle();
+        switch (method) {
+            case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: {
+                if (mLauncher == null) return null;
+
+                final float progress = LauncherState.OVERVIEW.getVerticalProgress(mLauncher)
+                        - LauncherState.ALL_APPS.getVerticalProgress(mLauncher);
+                final float distance = mLauncher.getAllAppsController().getShiftRange() * progress;
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
+                break;
+            }
+
+            case TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT: {
+                if (mLauncher == null) return null;
+
+                final float progress = LauncherState.NORMAL.getVerticalProgress(mLauncher)
+                        - LauncherState.ALL_APPS.getVerticalProgress(mLauncher);
+                final float distance = mLauncher.getAllAppsController().getShiftRange() * progress;
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
+                break;
+            }
+
+            case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
+                TestProtocol.sDebugTracing = true;
+                break;
+
+            case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
+                TestProtocol.sDebugTracing = false;
+                break;
+        }
+        return response;
+    }
+}
diff --git a/src/com/android/launcher3/testing/TestInformationProvider.java b/src/com/android/launcher3/testing/TestInformationProvider.java
new file mode 100644
index 0000000..bd177c0
--- /dev/null
+++ b/src/com/android/launcher3/testing/TestInformationProvider.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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.launcher3.testing;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.launcher3.Utilities;
+
+public class TestInformationProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
+        return 0;
+    }
+
+    @Override
+    public int delete(Uri uri, String s, String[] strings) {
+        return 0;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues contentValues) {
+        return null;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
+        return null;
+    }
+
+    @Override
+    public Bundle call(String method, String arg, Bundle extras) {
+        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+            TestInformationHandler handler = TestInformationHandler.newInstance(getContext());
+            handler.init(getContext());
+            return handler.call(method);
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
similarity index 96%
rename from src/com/android/launcher3/TestProtocol.java
rename to src/com/android/launcher3/testing/TestProtocol.java
index a0440e8..a678ef2 100644
--- a/src/com/android/launcher3/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.launcher3;
+package com.android.launcher3.testing;
 
 /**
  * Protocol for custom accessibility events for communication with UI Automation tests.
@@ -25,6 +25,7 @@
     public static final String STATE_FIELD = "state";
     public static final String SWITCHED_TO_STATE_MESSAGE = "TAPL_SWITCHED_TO_STATE";
     public static final String SCROLL_FINISHED_MESSAGE = "TAPL_SCROLL_FINISHED";
+    public static final String PAUSE_DETECTED_MESSAGE = "TAPL_PAUSE_DETECTED";
     public static final String RESPONSE_MESSAGE_POSTFIX = "_RESPONSE";
     public static final int NORMAL_STATE_ORDINAL = 0;
     public static final int SPRING_LOADED_STATE_ORDINAL = 1;
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 99b9f25..f858dc4 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -47,6 +47,7 @@
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.widget.PendingAppWidgetHostView;
 import com.android.launcher3.widget.WidgetAddFlowHandler;
@@ -66,15 +67,15 @@
     }
 
     private static void onClick(View v, String sourceContainer) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_START_TAG,
                     "onClick 1");
         }
         // Make sure that rogue clicks don't get through while allapps is launching, or after the
         // view has detached (it's possible for this to happen if the view is removed mid touch).
         if (v.getWindowToken() == null) {
-            if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+            if (TestProtocol.sDebugTracing) {
+                android.util.Log.d(TestProtocol.NO_START_TAG,
                         "onClick 2");
             }
             return;
@@ -82,8 +83,8 @@
 
         Launcher launcher = Launcher.getLauncher(v.getContext());
         if (!launcher.getWorkspace().isFinishedSwitchingState()) {
-            if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+            if (TestProtocol.sDebugTracing) {
+                android.util.Log.d(TestProtocol.NO_START_TAG,
                         "onClick 3");
             }
             return;
@@ -97,8 +98,8 @@
                 onClickFolderIcon(v);
             }
         } else if (tag instanceof AppInfo) {
-            if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+            if (TestProtocol.sDebugTracing) {
+                android.util.Log.d(TestProtocol.NO_START_TAG,
                         "onClick 4");
             }
             startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
@@ -232,8 +233,8 @@
 
     private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
             @Nullable String sourceContainer) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_START_TAG,
                     "startAppShortcutOrInfoActivity");
         }
         Intent intent;
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 4964182..939b0f2 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -41,6 +41,7 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.launcher3.util.TouchController;
@@ -213,8 +214,8 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (com.android.launcher3.TestProtocol.sDebugTracing) {
-            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+        if (TestProtocol.sDebugTracing) {
+            android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                     "onTouchEvent " + ev);
         }
         int action = ev.getAction();
@@ -226,8 +227,8 @@
         }
 
         if (mActiveController != null) {
-            if (com.android.launcher3.TestProtocol.sDebugTracing) {
-                android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+            if (TestProtocol.sDebugTracing) {
+                android.util.Log.d(TestProtocol.NO_DRAG_TAG,
                         "onTouchEvent 1");
             }
             return mActiveController.onControllerTouchEvent(ev);
@@ -495,12 +496,14 @@
         }
     }
 
+    @Override
     @TargetApi(Build.VERSION_CODES.Q)
-    public void updateTouchExcludeRegion(WindowInsets insets) {
+    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
         if (Utilities.ATLEAST_Q) {
             Insets gestureInsets = insets.getMandatorySystemGestureInsets();
             mSystemGestureRegion.set(gestureInsets.left, gestureInsets.top,
                     gestureInsets.right, gestureInsets.bottom);
         }
+        return super.dispatchApplyWindowInsets(insets);
     }
 }
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index f63bcdd..03cbb21 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -20,6 +20,7 @@
 import static com.android.launcher3.Utilities.mapToRange;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
+import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -40,7 +41,6 @@
 import android.os.Build;
 import android.os.CancellationSignal;
 import android.os.Handler;
-import android.os.Looper;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
@@ -63,7 +63,6 @@
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.shortcuts.DeepShortcutView;
-import com.android.launcher3.util.UiThreadHelper;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
@@ -180,6 +179,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         getViewTreeObserver().addOnGlobalLayoutListener(this);
+        mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK);
     }
 
     @Override
@@ -642,7 +642,7 @@
                 originalView.setVisibility(INVISIBLE);
             };
             CancellationSignal loadIconSignal = view.mLoadIconSignal;
-            new Handler(UiThreadHelper.getBackgroundLooper()).postAtFrontOfQueue(() -> {
+            new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(() -> {
                 view.getIcon(originalView, (ItemInfo) originalView.getTag(), isOpening,
                         onIconLoaded, loadIconSignal);
             });
diff --git a/tests/Android.mk b/tests/Android.mk
index 0991a04..978209f 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -32,7 +32,7 @@
     LOCAL_SRC_FILES := $(call all-java-files-under, tapl) \
         ../src/com/android/launcher3/ResourceUtils.java \
         ../src/com/android/launcher3/util/SecureSettingsObserver.java \
-        ../src/com/android/launcher3/TestProtocol.java
+        ../src/com/android/launcher3/testing/TestProtocol.java
 endif
 
 LOCAL_MODULE := ub-launcher-aosp-tapl
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 75ff66e..61c7306 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -184,5 +184,13 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity-alias>
+        <activity-alias android:name="Activity11"
+                        android:label="TestActivity11"
+                        android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity-alias>
     </application>
 </manifest>
diff --git a/tests/OWNERS b/tests/OWNERS
new file mode 100644
index 0000000..046d871
--- /dev/null
+++ b/tests/OWNERS
@@ -0,0 +1 @@
+vadimt@google.com
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 74cece8..44401c7 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -54,6 +54,7 @@
 import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.model.AppLaunchTracker;
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.tapl.TestHelpers;
 import com.android.launcher3.util.Wait;
@@ -91,7 +92,6 @@
 
     public static final long SHORT_UI_TIMEOUT = 300;
     public static final long DEFAULT_UI_TIMEOUT = 10000;
-    protected static final int LONG_WAIT_TIME_MS = 60000;
     private static final String TAG = "AbstractLauncherUiTest";
     private static int sScreenshotCount = 0;
 
@@ -198,6 +198,9 @@
 
     @Before
     public void setUp() throws Exception {
+        // Disable app tracker
+        AppLaunchTracker.INSTANCE.initializeForTesting(new AppLaunchTracker());
+
         mTargetContext = InstrumentationRegistry.getTargetContext();
         mTargetPackage = mTargetContext.getPackageName();
         // Unlock the phone
@@ -243,7 +246,7 @@
      */
     protected UiObject2 scrollAndFind(UiObject2 container, BySelector condition) {
         final int margin = ResourceUtils.getNavbarSize(
-                ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1;
+                ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mLauncher.getResources()) + 1;
         container.setGestureMargins(0, 0, 0, margin);
 
         int i = 0;
@@ -394,7 +397,7 @@
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         instrumentation.getTargetContext().startActivity(intent);
         assertTrue(packageName + " didn't start",
-                mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), LONG_WAIT_TIME_MS));
+                mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), DEFAULT_UI_TIMEOUT));
     }
 
     protected void startTestActivity(int activityNumber) {
@@ -410,7 +413,7 @@
         assertTrue(packageName + " didn't start",
                 mDevice.wait(
                         Until.hasObject(By.pkg(packageName).text("TestActivity" + activityNumber)),
-                        LONG_WAIT_TIME_MS));
+                        DEFAULT_UI_TIMEOUT));
     }
 
     protected static String resolveSystemApp(String category) {
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 70405fe..18a8f27 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -27,7 +27,7 @@
 import androidx.test.uiautomator.UiObject2;
 
 import com.android.launcher3.ResourceUtils;
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 
 /**
  * Operations on AllApps opened from Home. Also a parent for All Apps opened from Overview.
@@ -97,7 +97,7 @@
                     0,
                     getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1,
                     0,
-                    ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE,
+                    ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
                             mLauncher.getResources()) + 1);
             final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
             if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) {
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
index a472d31..f48d4dd 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
@@ -16,14 +16,14 @@
 
 package com.android.launcher3.tapl;
 
-import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
 
 import android.graphics.Point;
 
 import androidx.annotation.NonNull;
 import androidx.test.uiautomator.UiObject2;
 
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 
 /**
  * Operations on AllApps opened from Overview.
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 55e14cc..ce95298 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.tapl;
 
-import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
 
 import android.graphics.Point;
 import android.os.SystemClock;
@@ -24,7 +24,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 
 /**
  * Indicates the base state with a UI other than Overview running as foreground. It can also
@@ -32,7 +32,6 @@
  */
 public class Background extends LauncherInstrumentation.VisibleContainer {
     private static final int ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION = 500;
-    private static final int ZERO_BUTTON_SWIPE_UP_HOLD_DURATION = 400;
 
     Background(LauncherInstrumentation launcher) {
         super(launcher);
@@ -72,9 +71,15 @@
 
                 final long downTime = SystemClock.uptimeMillis();
                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
-                mLauncher.movePointer(
-                        downTime, downTime, ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION, start, end);
-                LauncherInstrumentation.sleep(ZERO_BUTTON_SWIPE_UP_HOLD_DURATION);
+                mLauncher.executeAndWaitForEvent(
+                        () -> mLauncher.movePointer(
+                                downTime,
+                                downTime,
+                                ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION,
+                                start,
+                                end),
+                        event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(event.getClassName()),
+                        "Pause wasn't detected");
                 mLauncher.sendPointer(
                         downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end);
                 break;
@@ -89,7 +94,7 @@
                 mLauncher.swipeToState(
                         centerX, startY, centerX,
                         startY - swipeHeight - mLauncher.getTouchSlop(),
-                        60,
+                        10,
                         expectedState);
                 break;
             }
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index 20c116c..cfc4374 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.tapl;
 
-import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
 
 import androidx.annotation.NonNull;
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 3295ddb..4261988 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -24,12 +24,13 @@
 import androidx.test.uiautomator.UiObject2;
 import androidx.test.uiautomator.Until;
 
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 
 /**
  * Ancestor for AppIcon and AppMenuItem.
  */
 abstract class Launchable {
+    private static final int WAIT_TIME_MS = 60000;
     protected final LauncherInstrumentation mLauncher;
 
     protected final UiObject2 mObject;
@@ -56,7 +57,7 @@
         mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
         mLauncher.assertTrue(
                 "Launching an app didn't open a new window: " + mObject.getText(),
-                mObject.clickAndWait(Until.newWindow(), LauncherInstrumentation.WAIT_TIME_MS));
+                mObject.clickAndWait(Until.newWindow(), WAIT_TIME_MS));
         mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
         mLauncher.assertTrue(
                 "App didn't start: " + selector,
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index a4711f5..a442e2b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -16,16 +16,23 @@
 
 package com.android.launcher3.tapl;
 
-import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
-import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DONT_KILL_APP;
+import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+
+import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
 import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
 
 import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -53,7 +60,7 @@
 import androidx.test.uiautomator.UiObject2;
 import androidx.test.uiautomator.Until;
 
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import org.junit.Assert;
@@ -115,7 +122,7 @@
     private static final String APPS_RES_ID = "apps_view";
     private static final String OVERVIEW_RES_ID = "overview_panel";
     private static final String WIDGETS_RES_ID = "widgets_list_view";
-    public static final int WAIT_TIME_MS = 60000;
+    public static final int WAIT_TIME_MS = 10000;
     private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
 
     private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
@@ -149,9 +156,10 @@
                 getLauncherPackageName() :
                 targetPackage;
 
+        String testProviderAuthority = authorityPackage + ".TestInfo";
         mTestProviderUri = new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(authorityPackage + ".TestInfo")
+                .authority(testProviderAuthority)
                 .build();
 
         try {
@@ -160,6 +168,25 @@
         } catch (IOException e) {
             fail(e.toString());
         }
+
+
+        PackageManager pm = getContext().getPackageManager();
+        ProviderInfo pi = pm.resolveContentProvider(
+                testProviderAuthority, MATCH_ALL | MATCH_DISABLED_COMPONENTS);
+        ComponentName cn = new ComponentName(pi.packageName, pi.name);
+
+        if (pm.getComponentEnabledSetting(cn) != COMPONENT_ENABLED_STATE_ENABLED) {
+            if (TestHelpers.isInLauncherProcess()) {
+                getContext().getPackageManager().setComponentEnabledSetting(
+                        cn, COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+            } else {
+                try {
+                    mDevice.executeShellCommand("pm enable " + cn.flattenToString());
+                } catch (IOException e) {
+                    fail(e.toString());
+                }
+            }
+        }
     }
 
     Context getContext() {
@@ -337,7 +364,7 @@
         }
     }
 
-    private Parcelable executeAndWaitForEvent(Runnable command,
+    Parcelable executeAndWaitForEvent(Runnable command,
             UiAutomation.AccessibilityEventFilter eventFilter, String message) {
         try {
             final AccessibilityEvent event =
@@ -541,25 +568,22 @@
 
     @NonNull
     UiObject2 waitForLauncherObject(String resName) {
-        final BySelector selector = getLauncherObjectSelector(resName);
-        final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
-        assertNotNull("Can't find a launcher object; selector: " + selector, object);
-        return object;
+        return waitForObjectBySelector(getLauncherObjectSelector(resName));
     }
 
     @NonNull
     UiObject2 waitForLauncherObjectByClass(String clazz) {
-        final BySelector selector = getLauncherObjectSelectorByClass(clazz);
-        final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
-        assertNotNull("Can't find a launcher object; selector: " + selector, object);
-        return object;
+        return waitForObjectBySelector(getLauncherObjectSelectorByClass(clazz));
     }
 
     @NonNull
     UiObject2 waitForFallbackLauncherObject(String resName) {
-        final BySelector selector = getFallbackLauncherObjectSelector(resName);
+        return waitForObjectBySelector(getFallbackLauncherObjectSelector(resName));
+    }
+
+    private UiObject2 waitForObjectBySelector(BySelector selector) {
         final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
-        assertNotNull("Can't find a fallback launcher object; selector: " + selector, object);
+        assertNotNull("Can't find a launcher object; selector: " + selector, object);
         return object;
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index ec99d26..058831f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.tapl;
 
-import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
 
 import androidx.annotation.NonNull;
 import androidx.test.uiautomator.UiObject2;
@@ -51,10 +51,9 @@
 
             // Swipe from an app icon to the top.
             LauncherInstrumentation.log("Overview.switchToAllApps before swipe");
-            final UiObject2 appIcon = mLauncher.waitForLauncherObjectByClass(
-                    "android.widget.TextView");
+            final UiObject2 allApps = mLauncher.waitForLauncherObject("apps_view");
             mLauncher.swipeToState(mLauncher.getDevice().getDisplayWidth() / 2,
-                    appIcon.getVisibleBounds().centerY(),
+                    allApps.getVisibleBounds().top,
                     mLauncher.getDevice().getDisplayWidth() / 2,
                     0, 50, ALL_APPS_STATE_ORDINAL);
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index b780df4..94003be 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -41,7 +41,7 @@
             LauncherInstrumentation.log("Widgets.flingForward enter");
             final UiObject2 widgetsContainer = verifyActiveContainer();
             widgetsContainer.setGestureMargins(0, 0, 0,
-                    ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE,
+                    ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
                             mLauncher.getResources()) + 1);
             widgetsContainer.fling(Direction.DOWN,
                     (int) (FLING_SPEED * mLauncher.getDisplayDensity()));
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 10b253d..7dcc426 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.tapl;
 
-import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
 
 import static junit.framework.TestCase.assertTrue;
 
@@ -30,7 +30,7 @@
 import androidx.test.uiautomator.Direction;
 import androidx.test.uiautomator.UiObject2;
 
-import com.android.launcher3.TestProtocol;
+import com.android.launcher3.testing.TestProtocol;
 
 /**
  * Operations on the workspace screen.