Merging ub-launcher3-qt-r1-dev, build 5749827

Test: Manual

Bug:136282913 P1 Swipe up from Assistant Fulfillment Card Jank
Bug:137129923 P1 Pixel launcher is leaking memory
Bug:137161198 P1 Unable to pull notification panel down with a swipe on home screen
Bug:137253043 P1 "Pixel Launcher keeps stopping" when scrolling through recent apps
Bug:137487381 P1 Overview goes back to fullscreen when swiping up during transition
Bug:137836033 P4 Fail to stop music due to "Swipe failed to receive an event for the swipe end"
Bug:138152531 P2 [Android Q][04713598] Launcher test cases are failed
Bug:138236583 P1 Icon scale is wrong when dragging from all apps or folders
Bug:138251824 P1 Flake: want to switch from background to overview; Swipe failed to receive an event for the swipe end
Bug:138252347 P1 qt-r1-dev Pixel Launcher flag ENABLE_HINTS_IN_OVERVIEW is Disable by Default
Change-Id: Idd0e987d26e1ffc75cdb9f90e9c08c26bb8c6503
diff --git a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 917800f..577b175 100644
--- a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -186,7 +186,7 @@
         return mMyBinder;
     }
 
-    public static boolean isInputMonitorInitialized() {
+    public static boolean isInitialized() {
         return true;
     }
 }
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index 60320d6..e1b71a0 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -22,6 +22,7 @@
 import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
+import androidx.annotation.NonNull;
 
 /**
  * This class will be moved to androidx library. There shouldn't be any dependency outside
@@ -154,7 +155,7 @@
      * @param scale                     returns the scale result from normalization
      * @return a bitmap suitable for disaplaying as an icon at various system UIs.
      */
-    public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
+    public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon, UserHandle user,
             boolean shrinkNonAdaptiveIcons, boolean isInstantApp, float[] scale) {
         if (scale == null) {
             scale = new float[1];
@@ -204,8 +205,11 @@
         mDisableColorExtractor = true;
     }
 
-    private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, boolean shrinkNonAdaptiveIcons,
-            RectF outIconBounds, float[] outScale) {
+    private Drawable normalizeAndWrapToAdaptiveIcon(@NonNull Drawable icon,
+            boolean shrinkNonAdaptiveIcons, RectF outIconBounds, float[] outScale) {
+        if (icon == null) {
+            return null;
+        }
         float scale = 1f;
 
         if (shrinkNonAdaptiveIcons && ATLEAST_OREO) {
@@ -261,7 +265,7 @@
      * @param icon drawable that should be flattened to a bitmap
      * @param scale the scale to apply before drawing {@param icon} on the canvas
      */
-    public Bitmap createIconBitmap(Drawable icon, float scale, int size) {
+    public Bitmap createIconBitmap(@NonNull Drawable icon, float scale, int size) {
         Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
         if (icon == null) {
             return bitmap;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index b507044..4eb9df2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -38,7 +38,7 @@
 
             case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
                 response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
-                        TouchInteractionService.isInputMonitorInitialized());
+                        TouchInteractionService.isInitialized());
                 return response;
             }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
index ddd28a3..ca89c33 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -19,12 +19,12 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
 
-import static com.android.launcher3.Utilities.FLAG_NO_GESTURES;
-
 import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
+import androidx.annotation.UiThread;
+
 import com.android.launcher3.util.Preconditions;
 import com.android.quickstep.inputconsumers.InputConsumer;
 import com.android.quickstep.util.SwipeAnimationTargetSet;
@@ -33,8 +33,6 @@
 import java.util.ArrayList;
 import java.util.function.Supplier;
 
-import androidx.annotation.UiThread;
-
 /**
  * Wrapper around RecentsAnimationController to help with some synchronization
  */
@@ -184,10 +182,7 @@
             }
         }
         if (mInputConsumer != null) {
-            int flags = ev.getEdgeFlags();
-            ev.setEdgeFlags(flags | FLAG_NO_GESTURES);
             mInputConsumer.onMotionEvent(ev);
-            ev.setEdgeFlags(flags);
         }
 
         return true;
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 debed89..6f36b05 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -33,11 +33,13 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
 
 import android.annotation.TargetApi;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.Service;
+import android.app.TaskInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -103,6 +105,7 @@
 import com.android.systemui.shared.system.RecentsAnimationListener;
 import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
 
+import com.android.systemui.shared.system.TaskInfoCompat;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -154,6 +157,7 @@
             MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
             MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
             MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
+            sIsInitialized = true;
         }
 
         @Override
@@ -227,15 +231,15 @@
     };
 
     private static boolean sConnected = false;
-    private static boolean sInputMonitorInitialized = false;
+    private static boolean sIsInitialized = false;
     private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
 
     public static boolean isConnected() {
         return sConnected;
     }
 
-    public static boolean isInputMonitorInitialized() {
-        return sInputMonitorInitialized;
+    public static boolean isInitialized() {
+        return sIsInitialized;
     }
 
     public static SwipeSharedState getSwipeSharedState() {
@@ -336,25 +340,32 @@
             mInputMonitorCompat.dispose();
             mInputMonitorCompat = null;
         }
-        sInputMonitorInitialized = false;
     }
 
     private void initInputMonitor() {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 1");
+        }
         if (!mMode.hasGestures || mISystemUiProxy == null) {
             return;
         }
         disposeEventHandlers();
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 2");
+        }
 
         try {
             mInputMonitorCompat = InputMonitorCompat.fromBundle(mISystemUiProxy
                     .monitorGestureInput("swipe-up", mDefaultDisplayId), KEY_EXTRA_INPUT_MONITOR);
             mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
                     mMainChoreographer, this::onInputEvent);
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 3");
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Unable to create input monitor", e);
         }
         initTouchBounds();
-        sInputMonitorInitialized = true;
     }
 
     private int getNavbarSize(String resName) {
@@ -408,6 +419,9 @@
 
     @Override
     public void onNavigationModeChanged(Mode newMode) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onNavigationModeChanged " + newMode);
+        }
         if (mMode.hasGestures != newMode.hasGestures) {
             if (newMode.hasGestures) {
                 getSystemService(DisplayManager.class).registerDisplayListener(
@@ -492,6 +506,7 @@
 
     @Override
     public void onDestroy() {
+        sIsInitialized = false;
         if (mIsUserUnlocked) {
             mInputConsumer.unregisterInputConsumer();
             mOverviewComponentObserver.onDestroy();
@@ -516,6 +531,9 @@
     }
 
     private void onInputEvent(InputEvent ev) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onInputEvent " + ev);
+        }
         if (!(ev instanceof MotionEvent)) {
             Log.e(TAG, "Unknown event " + ev);
             return;
@@ -567,7 +585,7 @@
             if (isInValidSystemUiState) {
                 // This handles apps launched in direct boot mode (e.g. dialer) as well as apps
                 // launched while device is locked even after exiting direct boot mode (e.g. camera).
-                return createDeviceLockedInputConsumer(mAM.getRunningTask(0));
+                return createDeviceLockedInputConsumer(mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
             } else {
                 return mResetGestureInputConsumer;
             }
@@ -605,7 +623,7 @@
     }
 
     private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
-        final RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
+        RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
         if (!useSharedState) {
             sSwipeSharedState.clearAllState(false /* finishAnimation */);
         }
@@ -617,6 +635,17 @@
         final ActivityControlHelper activityControl =
                 mOverviewComponentObserver.getActivityControlHelper();
 
+        boolean forceOverviewInputConsumer = false;
+        if (isExcludedAssistant(runningTaskInfo)) {
+            // In the case where we are in the excluded assistant state, ignore it and treat the
+            // running activity as the task behind the assistant
+            runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
+            final ComponentName homeComponent =
+                    mOverviewComponentObserver.getHomeIntent().getComponent();
+            forceOverviewInputConsumer =
+                    runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
+        }
+
         if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
                 && !sSwipeSharedState.recentsAnimationFinishInterrupted) {
             return mResetGestureInputConsumer;
@@ -626,7 +655,8 @@
             RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
             info.id = sSwipeSharedState.nextRunningTaskId;
             return createOtherActivityInputConsumer(event, info);
-        } else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()) {
+        } else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()
+                || forceOverviewInputConsumer) {
             return createOverviewInputConsumer(event);
         } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) {
             return createOverviewInputConsumer(event);
@@ -638,6 +668,12 @@
         }
     }
 
+    private boolean isExcludedAssistant(TaskInfo info) {
+        return info != null
+                && TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
+                && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
+    }
+
     private boolean disableHorizontalSwipe(MotionEvent event) {
         // mExclusionRegion can change on binder thread, use a local instance here.
         Region exclusionRegion = mExclusionRegion;
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 df37759..cc9719b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -56,6 +56,9 @@
 import android.view.WindowInsets;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
+
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
@@ -88,9 +91,6 @@
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 import com.android.systemui.shared.system.WindowCallbacksCompat;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.UiThread;
-
 @TargetApi(Build.VERSION_CODES.O)
 public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
         extends BaseSwipeUpHandler<T, RecentsView>
@@ -677,7 +677,7 @@
 
     @Override
     protected InputConsumer createNewInputProxyHandler() {
-        endRunningWindowAnim(true /* cancel */);
+        endRunningWindowAnim(mGestureEndTarget == HOME /* cancel */);
         endLauncherTransitionController();
         if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             // Hide the task view, if not already hidden
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index b566837..9b157d1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -474,11 +474,6 @@
     }
 
     @Override
-    protected boolean shouldBlockGestures(MotionEvent ev) {
-        return Utilities.shouldDisableGestures(ev);
-    }
-
-    @Override
     public boolean onTouchEvent(MotionEvent ev) {
         super.onTouchEvent(ev);
         final int x = (int) ev.getX();
@@ -1697,6 +1692,9 @@
      * @return How many pixels the running task is offset on the x-axis due to the current scrollX.
      */
     public float getScrollOffset() {
+        if (getRunningTaskIndex() == -1) {
+            return 0;
+        }
         int startScroll = getScrollForPage(getRunningTaskIndex());
         int offsetX = startScroll - getScrollX();
         offsetX *= getScaleX();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index d55a520..7f1e898 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -410,4 +410,11 @@
 
         return new ColorMatrixColorFilter(COLOR_MATRIX);
     }
+
+    public Bitmap getThumbnail() {
+        if (mThumbnailData == null) {
+            return null;
+        }
+        return mThumbnailData.thumbnail;
+    }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 3b35c86..b6cd1be 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -80,6 +80,7 @@
             return new Statement() {
                 @Override
                 public void evaluate() throws Throwable {
+                    mLauncher.enableDebugTracing();
                     final Context context = getInstrumentation().getContext();
                     final int currentInteractionMode =
                             LauncherInstrumentation.getCurrentInteractionMode(context);
@@ -104,6 +105,7 @@
                     } finally {
                         setActiveOverlay(prevOverlayPkg, originalMode);
                     }
+                    mLauncher.disableDebugTracing();
                 }
 
                 public void evaluateWithoutChangingSetting(Statement base) throws Throwable {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index bd52ffe..d2b8d4e 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -848,7 +848,7 @@
          */
 
         // Skip touch handling if there are no pages to swipe
-        if (getChildCount() <= 0 || shouldBlockGestures(ev)) return false;
+        if (getChildCount() <= 0) return false;
 
         acquireVelocityTrackerAndAddMovement(ev);
 
@@ -1093,14 +1093,10 @@
         mAllowOverScroll = enable;
     }
 
-    protected boolean shouldBlockGestures(MotionEvent ev) {
-        return false;
-    }
-
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         // Skip touch handling if there are no pages to swipe
-        if (getChildCount() <= 0 || shouldBlockGestures(ev)) return false;
+        if (getChildCount() <= 0) return false;
 
         acquireVelocityTrackerAndAddMovement(ev);
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 65aa3a7..fc5cd8a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
+
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.ActivityManager;
@@ -92,8 +94,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
-
 /**
  * Various utilities shared amongst the Launcher's classes.
  */
@@ -128,16 +128,6 @@
     public static final int EDGE_NAV_BAR = 1 << 8;
 
     /**
-     * Set on a motion event do disallow any gestures and only handle touch.
-     * See {@link MotionEvent#setEdgeFlags(int)}.
-     */
-    public static final int FLAG_NO_GESTURES = 1 << 9;
-
-    public static boolean shouldDisableGestures(MotionEvent ev) {
-        return (ev.getEdgeFlags() & FLAG_NO_GESTURES) == FLAG_NO_GESTURES;
-    }
-
-    /**
      * Indicates if the device has a debug build. Should only be used to store additional info or
      * add extra logging and not for changing the app behavior.
      */
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 45639e0..54efcb7 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/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index 7eb4015..9263a2a 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -29,6 +29,7 @@
 import android.view.View;
 
 import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
@@ -87,6 +88,9 @@
             Rect bounds = getDrawableBounds(d);
             destCanvas.translate(blurSizeOutline / 2 - bounds.left,
                     blurSizeOutline / 2 - bounds.top);
+            if (d instanceof FastBitmapDrawable) {
+                ((FastBitmapDrawable) d).setScale(1);
+            }
             d.draw(destCanvas);
         } else {
             final Rect clipRect = mTempRect;
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 079ab6d..9846a04 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -77,4 +77,6 @@
     public static boolean sDebugTracing = false;
     public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing";
     public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
+
+    public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824";
 }
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 594a246..f2f2f3b 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -21,7 +21,6 @@
 import static android.view.MotionEvent.ACTION_UP;
 
 import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
-import static com.android.launcher3.Utilities.shouldDisableGestures;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -30,7 +29,6 @@
 import android.graphics.RectF;
 import android.os.Build;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.Property;
 import android.view.MotionEvent;
 import android.view.View;
@@ -152,8 +150,6 @@
     }
 
     private TouchController findControllerToHandleTouch(MotionEvent ev) {
-        if (shouldDisableGestures(ev)) return null;
-
         AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
         if (topView != null && topView.onControllerInterceptTouchEvent(ev)) {
             return topView;
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 361f2fb..8dc8cea 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -17,6 +17,7 @@
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
+import static com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
 import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
 
 import static org.junit.Assert.assertTrue;
@@ -45,6 +46,7 @@
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.LauncherAppsCompat;
@@ -52,6 +54,7 @@
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.tapl.TestHelpers;
 import com.android.launcher3.testcomponent.TestCommandReceiver;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.FailureWatcher;
@@ -103,6 +106,10 @@
             Utilities.enableRunningInTestHarnessForTests();
             mLauncher.setSystemHealthSupplier(() -> TestCommandReceiver.callCommand(
                     TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE).getString("result"));
+            mLauncher.setOnSettledStateAction(
+                    containerType -> executeOnLauncher(
+                            launcher ->
+                                    checkLauncherIntegrity(launcher, containerType)));
         }
     }
 
@@ -379,4 +386,68 @@
     protected int getAllAppsScroll(Launcher launcher) {
         return launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY();
     }
+
+    private static void checkLauncherIntegrity(
+            Launcher launcher, ContainerType expectedContainerType) {
+        if (launcher != null) {
+            final LauncherStateManager stateManager = launcher.getStateManager();
+            final LauncherState stableState = stateManager.getCurrentStableState();
+
+            assertTrue("Stable state != state: " + stableState.getClass().getSimpleName() + ", "
+                            + stateManager.getState().getClass().getSimpleName(),
+                    stableState == stateManager.getState());
+
+            final boolean isResumed = launcher.hasBeenResumed();
+            assertTrue("hasBeenResumed() != isStarted(), hasBeenResumed(): " + isResumed,
+                    isResumed == launcher.isStarted());
+            assertTrue("hasBeenResumed() != isUserActive(), hasBeenResumed(): " + isResumed,
+                    isResumed == launcher.isUserActive());
+
+            final int ordinal = stableState.ordinal;
+
+            switch (expectedContainerType) {
+                case WORKSPACE:
+                case WIDGETS: {
+                    assertTrue(
+                            "Launcher is not resumed in state: " + expectedContainerType,
+                            isResumed);
+                    assertTrue(TestProtocol.stateOrdinalToString(ordinal),
+                            ordinal == TestProtocol.NORMAL_STATE_ORDINAL);
+                    break;
+                }
+                case ALL_APPS: {
+                    assertTrue(
+                            "Launcher is not resumed in state: " + expectedContainerType,
+                            isResumed);
+                    assertTrue(TestProtocol.stateOrdinalToString(ordinal),
+                            ordinal == TestProtocol.ALL_APPS_STATE_ORDINAL);
+                    break;
+                }
+                case OVERVIEW: {
+                    assertTrue(
+                            "Launcher is not resumed in state: " + expectedContainerType,
+                            isResumed);
+                    assertTrue(TestProtocol.stateOrdinalToString(ordinal),
+                            ordinal == TestProtocol.OVERVIEW_STATE_ORDINAL);
+                    break;
+                }
+                case BACKGROUND: {
+                    assertTrue("Launcher is resumed in state: " + expectedContainerType,
+                            !isResumed);
+                    assertTrue(TestProtocol.stateOrdinalToString(ordinal),
+                            ordinal == TestProtocol.NORMAL_STATE_ORDINAL);
+                    break;
+                }
+                default:
+                    throw new IllegalArgumentException(
+                            "Illegal container: " + expectedContainerType);
+            }
+        } else {
+            assertTrue(
+                    "Container type is not BACKGROUND or FALLBACK_OVERVIEW: "
+                            + expectedContainerType,
+                    expectedContainerType == ContainerType.BACKGROUND ||
+                            expectedContainerType == ContainerType.FALLBACK_OVERVIEW);
+        }
+    }
 }
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index 0f36292..ddcb4da 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -1,5 +1,6 @@
 package com.android.launcher3.ui;
 
+import android.util.Log;
 import android.view.Surface;
 
 import com.android.launcher3.tapl.TestHelpers;
@@ -9,6 +10,7 @@
 import org.junit.runners.model.Statement;
 
 class PortraitLandscapeRunner implements TestRule {
+    private static final String TAG = "PortraitLandscapeRunner";
     private AbstractLauncherUiTest mTest;
 
     public PortraitLandscapeRunner(AbstractLauncherUiTest test) {
@@ -36,6 +38,9 @@
 
                     evaluateInPortrait();
                     evaluateInLandscape();
+                } catch (Exception e) {
+                    Log.e(TAG, "Exception", e);
+                    throw e;
                 } finally {
                     mTest.mDevice.setOrientationNatural();
                     mTest.executeOnLauncher(launcher ->
diff --git a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
index 7f561a2..03d1600 100644
--- a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
+++ b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
@@ -16,10 +16,16 @@
 
 package com.android.launcher3.tapl;
 
+import static java.util.regex.Pattern.CASE_INSENSITIVE;
+
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.UiObject2;
 
+import java.util.regex.Pattern;
+
 public class AddToHomeScreenPrompt {
+    private static final Pattern ADD_AUTOMATICALLY =
+            Pattern.compile("^Add automatically$", CASE_INSENSITIVE);
     private final LauncherInstrumentation mLauncher;
     private final UiObject2 mWidgetCell;
 
@@ -33,9 +39,6 @@
     public void addAutomatically() {
         mLauncher.waitForObjectInContainer(
                 mWidgetCell.getParent().getParent().getParent().getParent(),
-                By.text(LauncherInstrumentation.isAvd()
-                        ? "ADD AUTOMATICALLY"
-                        : "Add automatically")).
-                click();
+                By.text(ADD_AUTOMATICALLY)).click();
     }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 060bf30..bcce8ef 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -54,7 +54,8 @@
                 "want to switch from background to overview")) {
             verifyActiveContainer();
             goToOverviewUnchecked(BACKGROUND_APP_STATE_ORDINAL);
-            return new BaseOverview(mLauncher);
+            return mLauncher.isFallbackOverview() ?
+                    new BaseOverview(mLauncher) : new Overview(mLauncher);
         }
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 04a0f12..bbd2c29 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -41,7 +41,7 @@
 
     @Override
     protected LauncherInstrumentation.ContainerType getContainerType() {
-        return LauncherInstrumentation.ContainerType.BASE_OVERVIEW;
+        return LauncherInstrumentation.ContainerType.FALLBACK_OVERVIEW;
     }
 
     /**
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index a5b0d25..f91e2ad 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -72,6 +72,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 /**
@@ -86,8 +87,8 @@
 
     // Types for launcher containers that the user is interacting with. "Background" is a
     // pseudo-container corresponding to inactive launcher covered by another app.
-    enum ContainerType {
-        WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, BASE_OVERVIEW
+    public enum ContainerType {
+        WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, FALLBACK_OVERVIEW
     }
 
     public enum NavigationModel {ZERO_BUTTON, TWO_BUTTON, THREE_BUTTON}
@@ -135,6 +136,8 @@
     private final Deque<String> mDiagnosticContext = new LinkedList<>();
     private Supplier<String> mSystemHealthSupplier;
 
+    private Consumer<ContainerType> mOnSettledStateAction;
+
     /**
      * Constructs the root of TAPL hierarchy. You get all other objects from it.
      */
@@ -296,6 +299,10 @@
         this.mSystemHealthSupplier = supplier;
     }
 
+    public void setOnSettledStateAction(Consumer<ContainerType> onSettledStateAction) {
+        mOnSettledStateAction = onSettledStateAction;
+    }
+
     private String getSystemHealthMessage() {
         final String testPackage = getContext().getPackageName();
         try {
@@ -396,7 +403,7 @@
     }
 
     private UiObject2 verifyContainerType(ContainerType containerType) {
-        //waitForTouchInteractionService();
+        waitForLauncherInitialized();
 
         assertEquals("Unexpected display rotation",
                 mExpectedRotation, mDevice.getDisplayRotation());
@@ -415,6 +422,14 @@
         assertTrue(error, error == null);
         log("verifyContainerType: " + containerType);
 
+        final UiObject2 container = verifyVisibleObjects(containerType);
+
+        if (mOnSettledStateAction != null) mOnSettledStateAction.accept(containerType);
+
+        return container;
+    }
+
+    private UiObject2 verifyVisibleObjects(ContainerType containerType) {
         try (Closable c = addContextLayer(
                 "but the current state is not " + containerType.name())) {
             switch (containerType) {
@@ -451,7 +466,7 @@
 
                     return waitForLauncherObject(OVERVIEW_RES_ID);
                 }
-                case BASE_OVERVIEW: {
+                case FALLBACK_OVERVIEW: {
                     return waitForFallbackLauncherObject(OVERVIEW_RES_ID);
                 }
                 case BACKGROUND: {
@@ -468,7 +483,7 @@
         }
     }
 
-    private void waitForTouchInteractionService() {
+    private void waitForLauncherInitialized() {
         for (int i = 0; i < 100; ++i) {
             if (getTestInfo(
                     TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED).
@@ -477,7 +492,7 @@
             }
             SystemClock.sleep(100);
         }
-        fail("TouchInteractionService didn't connect");
+        fail("Launcher didn't initialize");
     }
 
     Parcelable executeAndWaitForEvent(Runnable command,
@@ -739,6 +754,10 @@
         return mDevice.getLauncherPackageName();
     }
 
+    boolean isFallbackOverview() {
+        return !getOverviewPackageName().equals(getLauncherPackageName());
+    }
+
     @NonNull
     public UiDevice getDevice() {
         return mDevice;
@@ -774,7 +793,7 @@
                 startX = endX = rect.centerX();
                 final int vertCenter = rect.centerY();
                 final float halfGestureHeight = rect.height() * percent / 2.0f;
-                startY = (int) (vertCenter - halfGestureHeight);
+                startY = (int) (vertCenter - halfGestureHeight) + 1;
                 endY = (int) (vertCenter + halfGestureHeight);
             }
             break;
@@ -790,7 +809,7 @@
                 startY = endY = rect.centerY();
                 final int horizCenter = rect.centerX();
                 final float halfGestureWidth = rect.width() * percent / 2.0f;
-                startX = (int) (horizCenter - halfGestureWidth);
+                startX = (int) (horizCenter - halfGestureWidth) + 1;
                 endX = (int) (horizCenter + halfGestureWidth);
             }
             break;
@@ -817,6 +836,7 @@
     // Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
     // fixed interval each time.
     void linearGesture(int startX, int startY, int endX, int endY, int steps) {
+        log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
         final long downTime = SystemClock.uptimeMillis();
         final Point start = new Point(startX, startY);
         final Point end = new Point(endX, endY);
@@ -932,4 +952,12 @@
         getContext().getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(size);
         return size;
     }
+
+    public void enableDebugTracing() {
+        getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
+    }
+
+    public void disableDebugTracing() {
+        getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
+    }
 }
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
index e19f91a..ebe5eac 100644
--- a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
+++ b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
@@ -30,6 +30,7 @@
 
 import org.junit.Assert;
 
+import java.util.Date;
 import java.util.List;
 
 public class TestHelpers {
@@ -104,28 +105,21 @@
         DropBoxManager dropbox = (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE);
         Assert.assertNotNull("Unable access the DropBoxManager service", dropbox);
 
-        long timestamp = 0;
+        long timestamp = System.currentTimeMillis() - 5 * 60000;
         DropBoxManager.Entry entry;
-        int crashCount = 0;
         StringBuilder errorDetails = new StringBuilder();
         while (null != (entry = dropbox.getNextEntry(label, timestamp))) {
-            String dropboxSnippet;
-            try {
-                dropboxSnippet = entry.getText(4096);
-            } finally {
-                entry.close();
-            }
-
-            crashCount++;
-            errorDetails.append(label);
-            errorDetails.append(": ");
-            errorDetails.append(truncateCrash(dropboxSnippet, 40));
-            errorDetails.append("    ...\n");
-
             timestamp = entry.getTimeMillis();
+            errorDetails.append(new Date(timestamp));
+            errorDetails.append(": ");
+            errorDetails.append(entry.getTag());
+            errorDetails.append(": ");
+            final String dropboxSnippet = entry.getText(4096);
+            if (dropboxSnippet != null) errorDetails.append(truncateCrash(dropboxSnippet, 40));
+            errorDetails.append("    ...\n");
+            entry.close();
         }
-        Assert.assertEquals(errorDetails.toString(), 0, crashCount);
-        return crashCount > 0 ? errorDetails.toString() : null;
+        return errorDetails.length() != 0 ? errorDetails.toString() : null;
     }
 
     public static String getSystemHealthMessage(Context context) {
@@ -133,9 +127,15 @@
             StringBuilder errors = new StringBuilder();
 
             final String[] labels = {
+                    "system_app_anr",
+                    "system_app_crash",
+                    "system_app_native_crash",
+                    "system_app_wtf",
+                    "system_server_anr",
                     "system_server_crash",
                     "system_server_native_crash",
-                    "system_server_anr",
+                    "system_server_watchdog",
+                    "system_server_wtf",
             };
 
             for (String label : labels) {