Merge "Fix RequestPinItemTest, broken by my manual merge." into ub-launcher3-master
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/go/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index d0cfcf9..212ce9b 100644
--- a/go/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -32,6 +32,7 @@
 import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
 import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
 
+import android.content.Context;
 import android.view.View;
 
 import com.android.launcher3.DeviceProfile;
@@ -115,10 +116,10 @@
     }
 
     public static float getDefaultSwipeHeight(Launcher launcher) {
-        return getDefaultSwipeHeight(launcher.getDeviceProfile());
+        return getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
     }
 
-    public static float getDefaultSwipeHeight(DeviceProfile dp) {
+    public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) {
         return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 151ceb8..93d4de1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -32,6 +32,7 @@
 import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
 import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
 
+import android.content.Context;
 import android.graphics.Rect;
 import android.view.View;
 
@@ -159,11 +160,15 @@
     }
 
     public static float getDefaultSwipeHeight(Launcher launcher) {
-        return getDefaultSwipeHeight(launcher.getDeviceProfile());
+        return getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
     }
 
-    public static float getDefaultSwipeHeight(DeviceProfile dp) {
-        return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
+    public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) {
+        float swipeHeight = dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
+        if (SysUINavigationMode.getMode(context) == SysUINavigationMode.Mode.NO_BUTTON) {
+            swipeHeight -= dp.getInsets().bottom;
+        }
+        return swipeHeight;
     }
 
     @Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index ab346c0..4a3ad1d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -42,6 +42,7 @@
 import android.animation.AnimatorSet;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
+import android.view.View;
 import android.view.ViewConfiguration;
 
 import com.android.launcher3.Launcher;
@@ -179,6 +180,11 @@
         } else {
             super.onDragEnd(velocity, fling);
         }
+
+        View searchView = mLauncher.getAppsView().getSearchView();
+        if (searchView instanceof FeedbackHandler) {
+            ((FeedbackHandler) searchView).resetFeedback();
+        }
         mMotionPauseDetector.clear();
     }
 
@@ -205,4 +211,16 @@
             builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
         }
     }
+
+    /**
+     * Interface for views with feedback animation requiring reset
+     */
+    public interface FeedbackHandler {
+
+        /**
+         * reset searchWidget feedback
+         */
+        void resetFeedback();
+    }
+
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
index 4249f1d..c18b604 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
@@ -25,10 +25,12 @@
 import android.content.Context;
 import android.os.Build;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.ViewConfiguration;
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
 import com.android.quickstep.views.RecentsView;
@@ -159,6 +161,9 @@
 
         @Override
         public void run() {
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.ALL_APPS_UPON_RECENTS, "RecentsActivityCommand.run");
+            }
             long elapsedTime = mCreateTime - mLastToggleTime;
             mLastToggleTime = mCreateTime;
 
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 61b57e2..72a14b5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -25,7 +25,7 @@
         switch (method) {
             case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
                 final float swipeHeight =
-                        OverviewState.getDefaultSwipeHeight(mDeviceProfile);
+                        OverviewState.getDefaultSwipeHeight(mContext, mDeviceProfile);
                 response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
                 return response;
             }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
index 0acce02..8783ee3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
@@ -45,6 +45,7 @@
     public boolean goingToLauncher;
     public boolean recentsAnimationFinishInterrupted;
     public int nextRunningTaskId = -1;
+    private int mLogId;
 
     public void setOverviewComponentObserver(OverviewComponentObserver observer) {
         mOverviewComponentObserver = observer;
@@ -156,5 +157,10 @@
         pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
         pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled);
         pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning);
+        pw.println(prefix + "logTraceId=" + mLogId);
+    }
+
+    public void setLogTraceId(int logId) {
+        this.mLogId = logId;
     }
 }
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 440e8b9..716e8f4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -16,7 +16,6 @@
 package com.android.quickstep;
 
 import static android.view.MotionEvent.ACTION_DOWN;
-
 import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
 import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW;
@@ -68,11 +67,9 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.WindowManager;
-
 import androidx.annotation.BinderThread;
 import androidx.annotation.UiThread;
 import androidx.annotation.WorkerThread;
-
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
 import com.android.launcher3.ResourceUtils;
@@ -137,6 +134,13 @@
 public class TouchInteractionService extends Service implements
         NavigationModeChangeListener, DisplayListener {
 
+    /**
+     * NOTE: This value should be kept same as
+     * ActivityTaskManagerService#INTENT_EXTRA_LOG_TRACE_ID in platform
+     */
+    public static final String INTENT_EXTRA_LOG_TRACE_ID = "INTENT_EXTRA_LOG_TRACE_ID";
+
+
     public static final EventLogArray TOUCH_INTERACTION_LOG =
             new EventLogArray("touch_interaction_log", 40);
 
@@ -239,6 +243,7 @@
     private static boolean sConnected = false;
     private static boolean sIsInitialized = false;
     private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
+    private int mLogId;
 
     public static boolean isConnected() {
         return sConnected;
@@ -549,9 +554,12 @@
             Log.e(TAG, "Unknown event " + ev);
             return;
         }
+
         MotionEvent event = (MotionEvent) ev;
-        TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
         if (event.getAction() == ACTION_DOWN) {
+            mLogId = TOUCH_INTERACTION_LOG.generateAndSetLogId();
+            sSwipeSharedState.setLogTraceId(mLogId);
+
             if (mSwipeTouchRegion.contains(event.getX(), event.getY())) {
                 boolean useSharedState = mConsumer.useSharedSwipeState();
                 mConsumer.onConsumerAboutToBeSwitched();
@@ -571,6 +579,8 @@
                 mUncheckedConsumer = InputConsumer.NO_OP;
             }
         }
+
+        TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
         mUncheckedConsumer.onMotionEvent(event);
     }
 
@@ -656,7 +666,7 @@
                 final ComponentName homeComponent =
                     mOverviewComponentObserver.getHomeIntent().getComponent();
                 forceOverviewInputConsumer =
-                    runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
+                    runningTaskInfo.baseIntent.getComponent(). equals(homeComponent);
             }
         }
 
@@ -713,13 +723,13 @@
         return new OtherActivityInputConsumer(this, runningTaskInfo,
                 shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
                 sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
-                disableHorizontalSwipe(event), factory);
+                disableHorizontalSwipe(event), factory, mLogId);
     }
 
     private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
         if (mMode == Mode.NO_BUTTON && taskInfo != null) {
             return new DeviceLockedInputConsumer(this, sSwipeSharedState, mInputMonitorCompat,
-                    mSwipeTouchRegion, taskInfo.taskId);
+                    mSwipeTouchRegion, taskInfo.taskId, mLogId);
         } else {
             return mResetGestureInputConsumer;
         }
@@ -783,7 +793,8 @@
         }
 
         // Pass null animation handler to indicate this start is preload.
-        startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null);
+        startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
+                null);
     }
 
     @Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 3d763ab..0743925 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -18,12 +18,12 @@
 import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_POINTER_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
-
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.Utilities.squaredTouchSlop;
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
 import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
+import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -36,7 +36,6 @@
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
-
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.quickstep.LockScreenRecentsActivity;
@@ -76,6 +75,7 @@
 
     private final PointF mTouchDown = new PointF();
     private final ClipAnimationHelper mClipAnimationHelper;
+    private int mLogId;
     private final ClipAnimationHelper.TransformParams mTransformParams;
     private final Point mDisplaySize;
     private final MultiStateCallback mStateCallback;
@@ -90,11 +90,13 @@
     private SwipeAnimationTargetSet mTargetSet;
 
     public DeviceLockedInputConsumer(Context context, SwipeSharedState swipeSharedState,
-            InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId) {
+            InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId,
+            int logId) {
         mContext = context;
         mTouchSlopSquared = squaredTouchSlop(context);
         mSwipeSharedState = swipeSharedState;
         mClipAnimationHelper = new ClipAnimationHelper(context);
+        mLogId = logId;
         mTransformParams = new ClipAnimationHelper.TransformParams();
         mInputMonitorCompat = inputMonitorCompat;
         mSwipeTouchRegion = swipeTouchRegion;
@@ -205,7 +207,8 @@
         Intent intent = new Intent(Intent.ACTION_MAIN)
                 .addCategory(Intent.CATEGORY_DEFAULT)
                 .setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+                .putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
 
         mInputMonitorCompat.pilferPointers();
         startRecentsActivityAsync(intent, newListenerSet);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index 6ec1da0..e0ff8af 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -50,7 +50,6 @@
 import com.android.quickstep.util.ObjectWrapper;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.SwipeAnimationTargetSet;
-import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 86766d9..e41880d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -22,11 +22,11 @@
 import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.INVALID_POINTER_ID;
-
 import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.util.RaceConditionTracker.ENTER;
 import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
 import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
 import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -35,6 +35,7 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.Intent;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.os.Build;
@@ -43,12 +44,13 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
-
+import androidx.annotation.UiThread;
 import com.android.launcher3.R;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.RaceConditionTracker;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.BaseSwipeUpHandler;
+import com.android.quickstep.BaseSwipeUpHandler.Factory;
 import com.android.quickstep.OverviewCallbacks;
 import com.android.quickstep.SwipeSharedState;
 import com.android.quickstep.SysUINavigationMode;
@@ -59,11 +61,8 @@
 import com.android.quickstep.util.RecentsAnimationListenerSet;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputMonitorCompat;
-
 import java.util.function.Consumer;
 
-import androidx.annotation.UiThread;
-
 /**
  * Input consumer for handling events originating from an activity other than Launcher
  */
@@ -119,14 +118,16 @@
         ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
                 true /* restoreHomeStackPosition */);
     };
+    private int mLogId;
 
     public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
             boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
             Consumer<OtherActivityInputConsumer> onCompleteCallback,
             SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
             RectF swipeTouchRegion, boolean disableHorizontalSwipe,
-            BaseSwipeUpHandler.Factory handlerFactory) {
+            Factory handlerFactory, int logId) {
         super(base);
+        mLogId = logId;
 
         mMainThreadHandler = new Handler(Looper.getMainLooper());
         mRunningTask = runningTaskInfo;
@@ -341,7 +342,9 @@
             RecentsAnimationListenerSet newListenerSet =
                     mSwipeSharedState.newRecentsAnimationListenerSet();
             newListenerSet.addListener(handler);
-            startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
+            Intent intent = handler.getLaunchIntent();
+            intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
+            startRecentsActivityAsync(intent, newListenerSet);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 13a8dc2..bf3cd8a 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -16,11 +16,6 @@
 
 package com.android.quickstep.logging;
 
-import android.content.Context;
-import android.content.Intent;
-import android.stats.launcher.nano.LauncherExtension;
-import android.stats.launcher.nano.LauncherTarget;
-
 import static android.stats.launcher.nano.Launcher.ALLAPPS;
 import static android.stats.launcher.nano.Launcher.HOME;
 import static android.stats.launcher.nano.Launcher.LAUNCH_APP;
@@ -29,6 +24,11 @@
 import static android.stats.launcher.nano.Launcher.BACKGROUND;
 import static android.stats.launcher.nano.Launcher.OVERVIEW;
 
+import android.content.Context;
+import android.content.Intent;
+import android.stats.launcher.nano.Launcher;
+import android.stats.launcher.nano.LauncherExtension;
+import android.stats.launcher.nano.LauncherTarget;
 import android.view.View;
 
 import com.android.launcher3.ItemInfo;
@@ -39,8 +39,6 @@
 import com.android.systemui.shared.system.StatsLogCompat;
 import com.google.protobuf.nano.MessageNano;
 
-import androidx.annotation.Nullable;
-
 /**
  * This method calls the StatsLog hidden method until they are made available public.
  *
@@ -85,6 +83,17 @@
                 MessageNano.toByteArray(ext), true);
     }
 
+    @Override
+    public void logSwipeOnContainer(boolean isSwipingToLeft, int pageId) {
+        LauncherExtension ext = new LauncherExtension();
+        ext.srcTarget = new LauncherTarget[1];
+        int srcState = mStateProvider.getCurrentState();
+        fillInLauncherExtensionWithPageId(ext, pageId);
+        int launcherAction = isSwipingToLeft ? Launcher.SWIPE_LEFT : Launcher.SWIPE_RIGHT;
+        StatsLogCompat.write(launcherAction, srcState, srcState,
+                MessageNano.toByteArray(ext), true);
+    }
+
     public static boolean fillInLauncherExtension(View v, LauncherExtension extension) {
         StatsLogUtils.LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(v);
         if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
@@ -99,6 +108,13 @@
         return true;
     }
 
+    public static boolean fillInLauncherExtensionWithPageId(LauncherExtension ext, int pageId) {
+        Target target = new Target();
+        target.pageIndex = pageId;
+        copy(target, ext.srcTarget[0]);
+        return true;
+    }
+
     private static void copy(Target src, LauncherTarget dst) {
         // fill in
     }
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 3747f9a..dc6b56e 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -156,12 +156,14 @@
                 mDragHandleProgress = 1;
                 mMidAlpha = 0;
             } else {
-                mMidAlpha = Themes.getAttrInteger(getContext(), R.attr.allAppsInterimScrimAlpha);
+                Context context = getContext();
+                mMidAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha);
                 mMidProgress =  OVERVIEW.getVerticalProgress(mLauncher);
                 Rect hotseatPadding = dp.getHotseatLayoutPadding();
                 int hotseatSize = dp.hotseatBarSizePx + dp.getInsets().bottom
                         - hotseatPadding.bottom - hotseatPadding.top;
-                float dragHandleTop = Math.min(hotseatSize, OverviewState.getDefaultSwipeHeight(dp));
+                float dragHandleTop =
+                        Math.min(hotseatSize, OverviewState.getDefaultSwipeHeight(context, dp));
                 mDragHandleProgress =  1 - (dragHandleTop / mShiftRange);
             }
             mTopOffset = dp.getInsets().top - mShelfOffset;
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index f27f400..edd5011 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -34,9 +34,9 @@
 
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.util.rule.FailureWatcher;
 import com.android.systemui.shared.system.QuickStepContract;
 
-import org.junit.Assert;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
@@ -79,6 +79,14 @@
                 description.getAnnotation(NavigationModeSwitch.class) != null) {
             Mode mode = description.getAnnotation(NavigationModeSwitch.class).mode();
             return new Statement() {
+                private void assertTrue(String message, boolean condition) {
+                    if(!condition) {
+                        final AssertionError assertionError = new AssertionError(message);
+                        FailureWatcher.onError(mLauncher.getDevice(), description, assertionError);
+                        throw assertionError;
+                    }
+                }
+
                 @Override
                 public void evaluate() throws Throwable {
                     mLauncher.enableDebugTracing();
@@ -107,7 +115,8 @@
                         Log.e(TAG, "Exception", e);
                         throw e;
                     } finally {
-                        Assert.assertTrue(setActiveOverlay(prevOverlayPkg, originalMode));
+                        assertTrue("Couldn't set overlay",
+                                setActiveOverlay(prevOverlayPkg, originalMode));
                     }
                     mLauncher.disableDebugTracing();
                 }
@@ -176,7 +185,7 @@
                         latch.await(10, TimeUnit.SECONDS);
                         targetContext.getMainExecutor().execute(() ->
                                 sysUINavigationMode.removeModeChangeListener(listener));
-                        Assert.assertTrue("Navigation mode didn't change to " + expectedMode,
+                        assertTrue("Navigation mode didn't change to " + expectedMode,
                                 currentSysUiNavigationMode() == expectedMode);
                     }
 
@@ -184,7 +193,7 @@
                         if (mLauncher.getNavigationModel() == expectedMode) break;
                         Thread.sleep(100);
                     }
-                    Assert.assertTrue("Couldn't switch to " + overlayPackage,
+                    assertTrue("Couldn't switch to " + overlayPackage,
                             mLauncher.getNavigationModel() == expectedMode);
 
                     for (int i = 0; i != 100; ++i) {
@@ -192,7 +201,7 @@
                         Thread.sleep(100);
                     }
                     final String error = mLauncher.getNavigationModeMismatchError();
-                    Assert.assertTrue("Switching nav mode: " + error, error == null);
+                    assertTrue("Switching nav mode: " + error, error == null);
 
                     Thread.sleep(5000);
                     return true;
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 885fdbf..be8506d 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -97,6 +97,7 @@
     @Test
     @PortraitLandscape
     public void testOverview() throws Exception {
+        mLauncher.enableDebugTracing();
         startTestApps();
         Overview overview = mLauncher.pressHome().switchToOverview();
         assertTrue("Launcher internal state didn't switch to Overview",
@@ -176,6 +177,7 @@
         executeOnLauncher(
                 launcher -> assertEquals("Still have tasks after dismissing all",
                         0, getTaskCount(launcher)));
+        mLauncher.disableDebugTracing();
     }
 
     private int getCurrentOverviewPage(Launcher launcher) {
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 775885c..09608b5 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
-    <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="work_folder_name" msgid="3753320833950115786">"কাজ"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"অ্যাপ্লিকেশান ইনস্টল করা নেই৷"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"অ্যাপ্লিকেশান অনুপলব্ধ"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 3b0432e..8fa02c0 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
-    <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="work_folder_name" msgid="3753320833950115786">"कार्यस्‍थल"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"ऐप्‍लिकेशन इंस्‍टॉल नहीं है."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"ऐप्लिकेशन उपलब्ध नहीं है"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index fbb657e..93404e6 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
-    <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="work_folder_name" msgid="3753320833950115786">"Աշխատանքային"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Հավելվածը հասանելի չէ"</string>
@@ -87,7 +86,7 @@
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Հեռախոսը պտտելու դեպքում"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"Ծանուցումների կետիկներ"</string>
     <string name="notification_dots_desc_on" msgid="1679848116452218908">"Միացված է"</string>
-    <string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատած է"</string>
+    <string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատված է"</string>
     <string name="title_missing_notification_access" msgid="7503287056163941064">"Անհրաժեշտ է ծանուցման թույլտվություն"</string>
     <string name="msg_missing_notification_access" msgid="281113995110910548">"Ծանուցումների կետիկները ցուցադրելու համար միացրեք ծանուցումները <xliff:g id="NAME">%1$s</xliff:g>-ի համար"</string>
     <string name="title_change_settings" msgid="1376365968844349552">"Փոխել կարգավորումները"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index f4a328d..9738042 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
-    <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="work_folder_name" msgid="3753320833950115786">"ការងារ"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"មិន​បាន​ដំឡើង​កម្មវិធី។"</string>
     <string name="activity_not_available" msgid="7456344436509528827">"មិន​មាន​កម្មវិធី"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 046a662..d52446c 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
-    <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="work_folder_name" msgid="3753320833950115786">"Жумуш"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"Колдонмо орнотулган эмес."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"Колдонмо жеткиликтүү эмес"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index c8f70fe..1f8d3b8 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
-    <string name="folder_name" msgid="7371454440695724752"></string>
     <string name="work_folder_name" msgid="3753320833950115786">"కార్యాలయం"</string>
     <string name="activity_not_found" msgid="8071924732094499514">"యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
     <string name="activity_not_available" msgid="7456344436509528827">"యాప్ అందుబాటులో లేదు"</string>
@@ -53,7 +52,7 @@
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"అన్ఇన్‌స్టాల్ చేయి"</string>
     <string name="app_info_drop_target_label" msgid="692894985365717661">"యాప్ సమాచారం"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"ఇన్‌స్టాల్ చేయండి"</string>
-    <string name="permlab_install_shortcut" msgid="5632423390354674437">"సత్వరమార్గాలను ఇన్‌స్టాల్ చేయడం"</string>
+    <string name="permlab_install_shortcut" msgid="5632423390354674437">"షార్ట్‌కట్‌లను ఇన్‌స్టాల్ చేయడం"</string>
     <string name="permdesc_install_shortcut" msgid="923466509822011139">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_read_settings" msgid="1941457408239617576">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం"</string>
     <string name="permdesc_read_settings" msgid="5833423719057558387">"హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 8bf1a37..ac43967 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -38,10 +38,13 @@
 import android.util.Patterns;
 import android.util.Xml;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.LauncherProvider.SqlArguments;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.qsb.QsbContainerView;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Thunk;
@@ -84,7 +87,7 @@
 
         // Try with grid size and hotseat count
         String layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES_WITH_HOSTEAT,
-            grid.numColumns, grid.numRows, grid.numHotseatIcons);
+                grid.numColumns, grid.numRows, grid.numHotseatIcons);
         int layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
 
         // Try with only grid size
@@ -92,7 +95,7 @@
             Log.d(TAG, "Formatted layout: " + layoutName
                     + " not found. Trying layout without hosteat");
             layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES,
-                grid.numColumns, grid.numRows);
+                    grid.numColumns, grid.numRows);
             layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
         }
 
@@ -117,6 +120,7 @@
     private static final String TAG_AUTO_INSTALL = "autoinstall";
     private static final String TAG_FOLDER = "folder";
     private static final String TAG_APPWIDGET = "appwidget";
+    protected static final String TAG_SEARCH_WIDGET = "searchwidget";
     private static final String TAG_SHORTCUT = "shortcut";
     private static final String TAG_EXTRA = "extra";
 
@@ -148,8 +152,10 @@
     private static final String HOTSEAT_CONTAINER_NAME =
             Favorites.containerToString(Favorites.CONTAINER_HOTSEAT);
 
-    @Thunk final Context mContext;
-    @Thunk final AppWidgetHost mAppWidgetHost;
+    @Thunk
+    final Context mContext;
+    @Thunk
+    final AppWidgetHost mAppWidgetHost;
     protected final LayoutParserCallback mCallback;
 
     protected final PackageManager mPackageManager;
@@ -161,7 +167,8 @@
     private final int mColumnCount;
 
     private final int[] mTemp = new int[2];
-    @Thunk final ContentValues mValues;
+    @Thunk
+    final ContentValues mValues;
     protected final String mRootTag;
 
     protected SQLiteDatabase mDb;
@@ -245,7 +252,7 @@
      */
     protected int parseAndAddNode(
             XmlPullParser parser, ArrayMap<String, TagParser> tagParserMap, IntArray screenIds)
-        throws XmlPullParserException, IOException {
+            throws XmlPullParserException, IOException {
 
         if (TAG_INCLUDE.equals(parser.getName())) {
             final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
@@ -316,6 +323,7 @@
         parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
         parsers.put(TAG_FOLDER, new FolderParser());
         parsers.put(TAG_APPWIDGET, new PendingWidgetParser());
+        parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
         parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
         return parsers;
     }
@@ -348,15 +356,15 @@
                         info = mPackageManager.getActivityInfo(cn, 0);
                     } catch (PackageManager.NameNotFoundException nnfe) {
                         String[] packages = mPackageManager.currentToCanonicalPackageNames(
-                                new String[] { packageName });
+                                new String[]{packageName});
                         cn = new ComponentName(packages[0], className);
                         info = mPackageManager.getActivityInfo(cn, 0);
                     }
                     final Intent intent = new Intent(Intent.ACTION_MAIN, null)
-                        .addCategory(Intent.CATEGORY_LAUNCHER)
-                        .setComponent(cn)
-                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                            .addCategory(Intent.CATEGORY_LAUNCHER)
+                            .setComponent(cn)
+                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
 
                     return addShortcut(info.loadLabel(mPackageManager).toString(),
                             intent, Favorites.ITEM_TYPE_APPLICATION);
@@ -394,10 +402,10 @@
 
             mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON);
             final Intent intent = new Intent(Intent.ACTION_MAIN, null)
-                .addCategory(Intent.CATEGORY_LAUNCHER)
-                .setComponent(new ComponentName(packageName, className))
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                    .addCategory(Intent.CATEGORY_LAUNCHER)
+                    .setComponent(new ComponentName(packageName, className))
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
                     Favorites.ITEM_TYPE_APPLICATION);
         }
@@ -445,7 +453,7 @@
             mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
 
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             return addShortcut(mSourceRes.getString(titleResId),
                     intent, Favorites.ITEM_TYPE_SHORTCUT);
         }
@@ -470,12 +478,22 @@
      */
     protected class PendingWidgetParser implements TagParser {
 
-        @Override
-        public int parseAndAdd(XmlPullParser parser)
-                throws XmlPullParserException, IOException {
+        @Nullable
+        public ComponentName getComponentName(XmlPullParser parser) {
             final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
             final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
             if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
+                return null;
+            }
+            return new ComponentName(packageName, className);
+        }
+
+
+        @Override
+        public int parseAndAdd(XmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            ComponentName cn = getComponentName(parser);
+            if (cn == null) {
                 if (LOGD) Log.d(TAG, "Skipping invalid <appwidget> with no component");
                 return -1;
             }
@@ -506,16 +524,15 @@
                     throw new RuntimeException("Widgets can contain only extras");
                 }
             }
-
-            return verifyAndInsert(new ComponentName(packageName, className), extras);
+            return verifyAndInsert(cn, extras);
         }
 
         protected int verifyAndInsert(ComponentName cn, Bundle extras) {
             mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
             mValues.put(Favorites.RESTORED,
-                    LauncherAppWidgetInfo.FLAG_ID_NOT_VALID |
-                            LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY |
-                            LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
+                    LauncherAppWidgetInfo.FLAG_ID_NOT_VALID
+                            | LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY
+                            | LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
             mValues.put(Favorites._ID, mCallback.generateNewItemId());
             if (!extras.isEmpty()) {
                 mValues.put(Favorites.INTENT, new Intent().putExtras(extras).toUri(0));
@@ -530,6 +547,23 @@
         }
     }
 
+    protected class SearchWidgetParser extends PendingWidgetParser {
+        @Override
+        @Nullable
+        public ComponentName getComponentName(XmlPullParser parser) {
+            return QsbContainerView.getSearchComponentName(mContext);
+        }
+
+        @Override
+        protected int verifyAndInsert(ComponentName cn, Bundle extras) {
+            mValues.put(Favorites.OPTIONS, LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET);
+            int flags = mValues.getAsInteger(Favorites.RESTORED)
+                    | WorkspaceItemInfo.FLAG_RESTORE_STARTED;
+            mValues.put(Favorites.RESTORED, flags);
+            return super.verifyAndInsert(cn, extras);
+        }
+    }
+
     protected class FolderParser implements TagParser {
         private final ArrayMap<String, TagParser> mFolderElements;
 
@@ -681,7 +715,8 @@
         int insertAndCheck(SQLiteDatabase db, ContentValues values);
     }
 
-    @Thunk static void copyInteger(ContentValues from, ContentValues to, String key) {
+    @Thunk
+    static void copyInteger(ContentValues from, ContentValues to, String key) {
         to.put(key, from.getAsInteger(key));
     }
 }
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index 75297f6..af85594 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -14,13 +14,16 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
+
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.util.Thunk;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.List;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
 
 /**
  * Implements the layout parser with rules for internal layouts and partner layouts.
@@ -55,7 +58,8 @@
         return getFolderElementsMap(mSourceRes);
     }
 
-    @Thunk ArrayMap<String, TagParser> getFolderElementsMap(Resources res) {
+    @Thunk
+    ArrayMap<String, TagParser> getFolderElementsMap(Resources res) {
         ArrayMap<String, TagParser> parsers = new ArrayMap<>();
         parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
         parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
@@ -67,6 +71,7 @@
         ArrayMap<String, TagParser> parsers = new ArrayMap<>();
         parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
         parsers.put(TAG_APPWIDGET, new AppWidgetParser());
+        parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
         parsers.put(TAG_SHORTCUT, new UriShortcutParser(mSourceRes));
         parsers.put(TAG_RESOLVE, new ResolveParser());
         parsers.put(TAG_FOLDER, new MyFolderParser());
@@ -229,7 +234,8 @@
     /**
      * A parser which adds a folder whose contents come from partner apk.
      */
-    @Thunk class PartnerFolderParser implements TagParser {
+    @Thunk
+    class PartnerFolderParser implements TagParser {
 
         @Override
         public int parseAndAdd(XmlPullParser parser) throws XmlPullParserException,
@@ -255,7 +261,8 @@
     /**
      * An extension of FolderParser which allows adding items from a different xml.
      */
-    @Thunk class MyFolderParser extends FolderParser {
+    @Thunk
+    class MyFolderParser extends FolderParser {
 
         @Override
         public int parseAndAdd(XmlPullParser parser) throws XmlPullParserException,
@@ -281,7 +288,7 @@
                 mPackageManager.getReceiverInfo(cn, 0);
             } catch (Exception e) {
                 String[] packages = mPackageManager.currentToCanonicalPackageNames(
-                        new String[] { cn.getPackageName() });
+                        new String[]{cn.getPackageName()});
                 cn = new ComponentName(packages[0], cn.getClassName());
                 try {
                     mPackageManager.getReceiverInfo(cn, 0);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index cdb16d2..aa02441 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -110,6 +110,7 @@
 import com.android.launcher3.notification.NotificationListener;
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.qsb.QsbContainerView;
 import com.android.launcher3.states.InternalStateHandler;
 import com.android.launcher3.states.RotationHelper;
 import com.android.launcher3.touch.ItemClickHandler;
@@ -210,7 +211,8 @@
     // How long to wait before the new-shortcut animation automatically pans the workspace
     private static final int NEW_APPS_PAGE_MOVE_DELAY = 500;
     private static final int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
-    @Thunk static final int NEW_APPS_ANIMATION_DELAY = 500;
+    @Thunk
+    static final int NEW_APPS_ANIMATION_DELAY = 500;
 
     private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 1;
     private static final int SCRIM_VIEW_ALPHA_CHANNEL_INDEX = 0;
@@ -218,9 +220,11 @@
     private LauncherAppTransitionManager mAppTransitionManager;
     private Configuration mOldConfig;
 
-    @Thunk Workspace mWorkspace;
+    @Thunk
+    Workspace mWorkspace;
     private View mLauncherView;
-    @Thunk DragLayer mDragLayer;
+    @Thunk
+    DragLayer mDragLayer;
     private DragController mDragController;
 
     private AppWidgetManagerCompat mAppWidgetManager;
@@ -228,21 +232,25 @@
 
     private final int[] mTmpAddItemCellCoordinates = new int[2];
 
-    @Thunk Hotseat mHotseat;
+    @Thunk
+    Hotseat mHotseat;
 
     private DropTargetBar mDropTargetBar;
 
     // Main container view for the all apps screen.
-    @Thunk AllAppsContainerView mAppsView;
+    @Thunk
+    AllAppsContainerView mAppsView;
     AllAppsTransitionController mAllAppsController;
 
     // Scrim view for the all apps and overview state.
-    @Thunk ScrimView mScrimView;
+    @Thunk
+    ScrimView mScrimView;
 
     // UI and state for the overview panel
     private View mOverviewPanel;
 
-    @Thunk boolean mWorkspaceLoading = true;
+    @Thunk
+    boolean mWorkspaceLoading = true;
 
     private ArrayList<OnResumeCallback> mOnResumeCallbacks = new ArrayList<>();
 
@@ -387,7 +395,8 @@
         RaceConditionTracker.onEvent(ON_CREATE_EVT, EXIT);
         mStateManager.addStateListener(new LauncherStateManager.StateListener() {
             @Override
-            public void onStateTransitionStart(LauncherState toState) {}
+            public void onStateTransitionStart(LauncherState toState) {
+            }
 
             @Override
             public void onStateTransitionComplete(LauncherState finalState) {
@@ -640,7 +649,8 @@
                             .getLauncherAppWidgetInfo(widgetId);
                     if (provider != null) {
                         new WidgetAddFlowHandler(provider)
-                                .startConfigActivity(this, widgetInfo, REQUEST_RECONFIGURE_APPWIDGET);
+                                .startConfigActivity(this, widgetInfo,
+                                        REQUEST_RECONFIGURE_APPWIDGET);
                     }
                 }
                 break;
@@ -828,7 +838,8 @@
         }
     }
 
-    @Thunk void completeTwoStageWidgetDrop(
+    @Thunk
+    void completeTwoStageWidgetDrop(
             final int resultCode, final int appWidgetId, final PendingRequestArgs requestArgs) {
         CellLayout cellLayout = mWorkspace.getScreenWithId(requestArgs.screenId);
         Runnable onCompleteRunnable = null;
@@ -925,7 +936,7 @@
         int containerType = mStateManager.getState().containerType;
         if (containerType == ContainerType.WORKSPACE && mWorkspace != null) {
             getUserEventDispatcher().logActionCommand(command,
-                containerType, -1, mWorkspace.isOverlayShown() ? -1 : 0);
+                    containerType, -1, mWorkspace.isOverlayShown() ? -1 : 0);
         } else {
             getUserEventDispatcher().logActionCommand(command, containerType, -1);
         }
@@ -1054,7 +1065,8 @@
             mStateManager.goToState(state, false /* animated */);
         }
 
-        PendingRequestArgs requestArgs = savedState.getParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS);
+        PendingRequestArgs requestArgs = savedState.getParcelable(
+                RUNTIME_STATE_PENDING_REQUEST_ARGS);
         if (requestArgs != null) {
             setWaitingForResult(requestArgs);
         }
@@ -1124,8 +1136,7 @@
      * Creates a view representing a shortcut inflated from the specified resource.
      *
      * @param parent The group the shortcut belongs to.
-     * @param info The data structure describing the shortcut.
-     *
+     * @param info   The data structure describing the shortcut.
      * @return A View inflated from layoutResId.
      */
     public View createShortcut(ViewGroup parent, WorkspaceItemInfo info) {
@@ -1227,7 +1238,8 @@
      *
      * @param appWidgetId The app widget id
      */
-    @Thunk void completeAddAppWidget(int appWidgetId, ItemInfo itemInfo,
+    @Thunk
+    void completeAddAppWidget(int appWidgetId, ItemInfo itemInfo,
             AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo) {
 
         if (appWidgetInfo == null) {
@@ -1345,7 +1357,9 @@
         return mSharedPrefs;
     }
 
-    public int getOrientation() { return mOldConfig.orientation; }
+    public int getOrientation() {
+        return mOldConfig.orientation;
+    }
 
     @Override
     protected void onNewIntent(Intent intent) {
@@ -1569,7 +1583,8 @@
 
     void addAppWidgetImpl(int appWidgetId, ItemInfo info,
             AppWidgetHostView boundWidget, WidgetAddFlowHandler addFlowHandler, int delay) {
-        if (!addFlowHandler.startConfigActivity(this, appWidgetId, info, REQUEST_CREATE_APPWIDGET)) {
+        if (!addFlowHandler.startConfigActivity(this, appWidgetId, info,
+                REQUEST_CREATE_APPWIDGET)) {
             // If the configuration flow was not started, add the widget
 
             Runnable onComplete = new Runnable() {
@@ -1579,7 +1594,8 @@
                     mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
                 }
             };
-            completeAddAppWidget(appWidgetId, info, boundWidget, addFlowHandler.getProviderInfo(this));
+            completeAddAppWidget(appWidgetId, info, boundWidget,
+                    addFlowHandler.getProviderInfo(this));
             mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete, delay, false);
         }
     }
@@ -1605,7 +1621,7 @@
                 break;
             default:
                 throw new IllegalStateException("Unknown item type: " + info.itemType);
-            }
+        }
     }
 
     /**
@@ -1780,7 +1796,7 @@
 
     @Override
     public int getCurrentState() {
-        if(mStateManager.getState() == LauncherState.ALL_APPS) {
+        if (mStateManager.getState() == LauncherState.ALL_APPS) {
             return StatsLogUtils.LAUNCHER_STATE_ALLAPPS;
         } else if (mStateManager.getState() == OVERVIEW) {
             return StatsLogUtils.LAUNCHER_STATE_OVERVIEW;
@@ -2043,7 +2059,7 @@
                     throw new RuntimeException("Invalid Item Type");
             }
 
-             /*
+            /*
              * Remove colliding items.
              */
             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
@@ -2115,6 +2131,14 @@
     }
 
     private View inflateAppWidget(LauncherAppWidgetInfo item) {
+        if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
+            item.providerName = QsbContainerView.getSearchComponentName(this);
+            if (item.providerName == null) {
+                getModelWriter().deleteItemFromDatabase(item);
+                return null;
+            }
+        }
+
         if (mIsSafeModeEnabled) {
             PendingAppWidgetHostView view =
                     new PendingAppWidgetHostView(this, item, mIconCache, true);
@@ -2161,7 +2185,8 @@
                     pendingInfo.spanY = item.spanY;
                     pendingInfo.minSpanX = item.minSpanX;
                     pendingInfo.minSpanY = item.minSpanY;
-                    Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);
+                    Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this,
+                            pendingInfo);
 
                     boolean isDirectConfig =
                             item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
@@ -2508,8 +2533,8 @@
                     if (focusedView instanceof BubbleTextView
                             && focusedView.getTag() instanceof ItemInfo
                             && mAccessibilityDelegate.performAction(focusedView,
-                                    (ItemInfo) focusedView.getTag(),
-                                    LauncherAccessibilityDelegate.DEEP_SHORTCUTS)) {
+                            (ItemInfo) focusedView.getTag(),
+                            LauncherAccessibilityDelegate.DEEP_SHORTCUTS)) {
                         PopupContainerWithArrow.getOpen(this).requestFocus();
                         return true;
                     }
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 051846c..b824301 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -29,6 +29,9 @@
  */
 public class LauncherAppWidgetInfo extends ItemInfo {
 
+    public static final int OPTION_SEARCH_WIDGET = 1;
+
+
     public static final int RESTORE_COMPLETED = 0;
 
     /**
@@ -97,6 +100,11 @@
     public Intent bindOptions;
 
     /**
+     * Widget options
+     */
+    public int options;
+
+    /**
      * Nonnull for pending widgets. We use this to get the icon and title for the widget.
      */
     public PackageItemInfo pendingItemInfo;
@@ -137,6 +145,7 @@
         writer.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId)
                 .put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString())
                 .put(LauncherSettings.Favorites.RESTORED, restoreStatus)
+                .put(LauncherSettings.Favorites.OPTIONS, options)
                 .put(LauncherSettings.Favorites.INTENT, bindOptions);
     }
 
@@ -164,4 +173,13 @@
     public final boolean hasRestoreFlag(int flag) {
         return (restoreStatus & flag) == flag;
     }
+
+    /**
+     * returns if widget options include an option or not
+     * @param option
+     * @return
+     */
+    public final boolean hasOptionFlag(int option) {
+        return (options & option) != 0;
+    }
 }
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index d66e581..e1ea3be 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -227,6 +227,10 @@
 
     private void goToState(LauncherState state, boolean animated, long delay,
             final Runnable onCompleteRunnable) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.ALL_APPS_UPON_RECENTS, "goToState: " + state + " @ " +
+                    Log.getStackTraceString(new Throwable()));
+        }
         animated &= Utilities.areAnimationsEnabled(mLauncher);
         if (mLauncher.isInState(state)) {
             if (mConfig.mCurrentAnimation == null) {
@@ -426,6 +430,9 @@
         if (state != mCurrentStableState) {
             mLastStableState = state.getHistoryForState(mCurrentStableState);
             mCurrentStableState = state;
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.ALL_APPS_UPON_RECENTS, "onStateTransitionEnd: " + state);
+            }
         }
 
         state.onStateTransitionEnd(mLauncher);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index bbb3915..f9a326f 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1289,6 +1289,10 @@
         if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
             switch (event.getAction()) {
                 case MotionEvent.ACTION_SCROLL: {
+                    Launcher launcher = Launcher.getLauncher(getContext());
+                    if (launcher != null) {
+                        AbstractFloatingView.closeAllOpenViews(launcher);
+                    }
                     // Handle mouse (or ext. device) by shifting the page depending on the scroll
                     final float vscroll;
                     final float hscroll;
@@ -1299,6 +1303,9 @@
                         vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
                         hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
                     }
+                    if (Math.abs(vscroll) > Math.abs(hscroll) && !isVerticalScrollable()) {
+                        return true;
+                    }
                     if (hscroll != 0 || vscroll != 0) {
                         boolean isForwardScroll = mIsRtl ? (hscroll < 0 || vscroll < 0)
                                                          : (hscroll > 0 || vscroll > 0);
@@ -1315,6 +1322,10 @@
         return super.onGenericMotionEvent(event);
     }
 
+    protected boolean isVerticalScrollable() {
+        return true;
+    }
+
     private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index d9eb311..1b757d5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1053,6 +1053,7 @@
             if (!mOverlayShown) {
                 mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
                         Action.Direction.LEFT, ContainerType.WORKSPACE, 0);
+                mLauncher.getStatsLogManager().logSwipeOnContainer(true, 0);
             }
             mOverlayShown = true;
             // Not announcing the overlay page for accessibility since it announces itself.
@@ -1062,6 +1063,7 @@
                 if (!ued.isPreviousHomeGesture()) {
                     mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
                         Action.Direction.RIGHT, ContainerType.WORKSPACE, -1);
+                    mLauncher.getStatsLogManager().logSwipeOnContainer(false, -1);
                 }
             } else if (Float.compare(mOverlayTranslation, 0f) != 0) {
                 // When arriving to 0 overscroll from non-zero overscroll, announce page for
@@ -2531,22 +2533,22 @@
             View view;
 
             switch (info.itemType) {
-            case ITEM_TYPE_APPLICATION:
-            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
-            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
-                if (info.container == NO_ID && info instanceof AppInfo) {
-                    // Came from all apps -- make a copy
-                    info = ((AppInfo) info).makeWorkspaceItem();
-                    d.dragInfo = info;
-                }
-                view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
-                break;
-            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
-                view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
-                        (FolderInfo) info);
-                break;
-            default:
-                throw new IllegalStateException("Unknown item type: " + info.itemType);
+                case ITEM_TYPE_APPLICATION:
+                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+                    if (info instanceof AppInfo) {
+                        // Came from all apps -- make a copy
+                        info = ((AppInfo) info).makeWorkspaceItem();
+                        d.dragInfo = info;
+                    }
+                    view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
+                    break;
+                case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                    view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
+                            (FolderInfo) info);
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown item type: " + info.itemType);
             }
 
             // First we find the cell nearest to point at which the item is
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 4a2109e..293b867 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -628,20 +628,4 @@
 
         return super.performAccessibilityAction(action, arguments);
     }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        final boolean result = super.dispatchTouchEvent(ev);
-        switch (ev.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                if (result) mAllAppsStore.enableDeferUpdates(
-                        AllAppsStore.DEFER_UPDATES_USER_INTERACTION);
-                break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                mAllAppsStore.disableDeferUpdates(AllAppsStore.DEFER_UPDATES_USER_INTERACTION);
-                break;
-        }
-        return result;
-    }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index 69068c6..5b73940 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -81,4 +81,9 @@
     public boolean hasOverlappingRendering() {
         return false;
     }
+
+    @Override
+    protected boolean isVerticalScrollable() {
+        return false;
+    }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index a505240..c4b2f68 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -41,10 +41,8 @@
 
     // Defer updates flag used to defer all apps updates to the next draw.
     public static final int DEFER_UPDATES_NEXT_DRAW = 1 << 0;
-    // Defer updates flag used to defer all apps updates while the user interacts with all apps.
-    public static final int DEFER_UPDATES_USER_INTERACTION = 1 << 1;
     // Defer updates flag used to defer all apps updates by a test's request.
-    public static final int DEFER_UPDATES_TEST = 1 << 2;
+    public static final int DEFER_UPDATES_TEST = 1 << 1;
 
     private PackageUserKey mTempKey = new PackageUserKey(null, null);
     private AppInfo mTempInfo = new AppInfo();
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index 1d19b53..1885d8f 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -31,11 +31,14 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.Log;
 
 import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVL;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.PackageUserKey;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import androidx.annotation.NonNull;
@@ -167,6 +170,10 @@
 
         @Override
         public void onPackagesSuspended(String[] packageNames, UserHandle user) {
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.APP_NOT_DISABLED, "onPackagesSuspended: " +
+                        Arrays.toString(packageNames));
+            }
             mCallback.onPackagesSuspended(packageNames, user);
         }
 
diff --git a/src/com/android/launcher3/logging/EventLogArray.java b/src/com/android/launcher3/logging/EventLogArray.java
index f20f365..3ecfb23 100644
--- a/src/com/android/launcher3/logging/EventLogArray.java
+++ b/src/com/android/launcher3/logging/EventLogArray.java
@@ -16,11 +16,13 @@
 package com.android.launcher3.logging;
 
 
+import android.util.Log;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.Locale;
+import java.util.Random;
 
 /**
  * A utility class to record and log events. Events are stored in a fixed size array and old logs
@@ -37,6 +39,7 @@
     private final String name;
     private final EventEntry[] logs;
     private int nextIndex;
+    private int mLogId;
 
     public EventLogArray(String name, int size) {
         this.name = name;
@@ -52,10 +55,6 @@
         addLog(TYPE_INTEGER, event, extras);
     }
 
-    public void addLog(String event, float extras) {
-        addLog(TYPE_FLOAT, event, extras);
-    }
-
     public void addLog(String event, boolean extras) {
         addLog(extras ? TYPE_BOOL_TRUE : TYPE_BOOL_FALSE, event, 0);
     }
@@ -65,7 +64,7 @@
         int last = (nextIndex + logs.length - 1) % logs.length;
         int secondLast = (nextIndex + logs.length - 2) % logs.length;
         if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) {
-            logs[last].update(type, event, extras);
+            logs[last].update(type, event, extras, mLogId);
             logs[secondLast].duplicateCount++;
             return;
         }
@@ -73,7 +72,7 @@
         if (logs[nextIndex] == null) {
             logs[nextIndex] = new EventEntry();
         }
-        logs[nextIndex].update(type, event, extras);
+        logs[nextIndex].update(type, event, extras, mLogId);
         nextIndex = (nextIndex + 1) % logs.length;
     }
 
@@ -113,10 +112,18 @@
             if (log.duplicateCount > 0) {
                 msg.append(" & ").append(log.duplicateCount).append(" similar events");
             }
+            msg.append(" traceId: ").append(log.traceId);
             writer.println(msg);
         }
     }
 
+    /** Returns a 3 digit random number between 100-999 */
+    public int generateAndSetLogId() {
+        Random r = new Random();
+        mLogId = r.nextInt(900) + 100;
+        return mLogId;
+    }
+
     private boolean isEntrySame(EventEntry entry, int type, String event) {
         return entry != null && entry.type == type && entry.event.equals(event);
     }
@@ -129,11 +136,13 @@
         private float extras;
         private long time;
         private int duplicateCount;
+        private int traceId;
 
-        public void update(int type, String event, float extras) {
+        public void update(int type, String event, float extras, int traceId) {
             this.type = type;
             this.event = event;
             this.extras = extras;
+            this.traceId = traceId;
             time = System.currentTimeMillis();
             duplicateCount = 0;
         }
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index d11d434..cad95b0 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -41,5 +41,6 @@
     public void logAppLaunch(View v, Intent intent) { }
     public void logTaskLaunch(View v, ComponentKey key) { }
     public void logTaskDismiss(View v, ComponentKey key) { }
+    public void logSwipeOnContainer(boolean isSwipingToLeft, int pageId) { }
     public void verify() {}     // TODO: should move into robo tests
 }
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 8845ab3..60e917d 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -66,6 +66,7 @@
 import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.provider.ImportDataTask;
+import com.android.launcher3.qsb.QsbContainerView;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.util.ComponentKey;
@@ -580,10 +581,19 @@
 
                             int appWidgetId = c.getInt(appWidgetIdIndex);
                             String savedProvider = c.getString(appWidgetProviderIndex);
+                            final ComponentName component;
 
-                            final ComponentName component =
-                                    ComponentName.unflattenFromString(savedProvider);
-
+                            boolean isSearchWidget = (c.getInt(optionsIndex)
+                                    & LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET) != 0;
+                            if (isSearchWidget) {
+                                component  = QsbContainerView.getSearchComponentName(context);
+                                if (component == null) {
+                                    c.markDeleted("Discarding SearchWidget without packagename ");
+                                    continue;
+                                }
+                            } else {
+                                component = ComponentName.unflattenFromString(savedProvider);
+                            }
                             final boolean isIdValid = !c.hasRestoreFlag(
                                     LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
                             final boolean wasProviderReady = !c.hasRestoreFlag(
@@ -593,9 +603,7 @@
                                 widgetProvidersMap = mAppWidgetManager.getAllProvidersMap();
                             }
                             final AppWidgetProviderInfo provider = widgetProvidersMap.get(
-                                    new ComponentKey(
-                                            ComponentName.unflattenFromString(savedProvider),
-                                            c.user));
+                                    new ComponentKey(component, c.user));
 
                             final boolean isProviderReady = isValidProvider(provider);
                             if (!isSafeMode && !customWidget &&
@@ -659,6 +667,7 @@
                                 c.applyCommonProperties(appWidgetInfo);
                                 appWidgetInfo.spanX = c.getInt(spanXIndex);
                                 appWidgetInfo.spanY = c.getInt(spanYIndex);
+                                appWidgetInfo.options = c.getInt(optionsIndex);
                                 appWidgetInfo.user = c.user;
 
                                 if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 4adf59a..e6a1a0b 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -39,6 +39,7 @@
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.IntSparseArrayMap;
 import com.android.launcher3.util.ItemInfoMatcher;
@@ -84,6 +85,10 @@
 
     @Override
     public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.APP_NOT_DISABLED, "PackageUpdatedTask: " + mOp + ", " +
+                    Arrays.toString(mPackages));
+        }
         final Context context = app.getContext();
         final IconCache iconCache = app.getIconCache();
 
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 1296a96..2a40d68 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -166,7 +166,10 @@
     }
 
     public OnClickListener getItemClickListener() {
-        return ItemClickHandler.INSTANCE;
+        return (view) -> {
+            ItemClickHandler.INSTANCE.onClick(view);
+            close(true);
+        };
     }
 
     @Override
@@ -564,9 +567,9 @@
 
     @Override
     protected void closeComplete() {
-        super.closeComplete();
         mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible());
         mOriginalIcon.forceHideDot(false);
+        super.closeComplete();
     }
 
     @Override
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index 09c6c36..0eb4285 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -39,6 +39,7 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.AppWidgetResizeFrame;
@@ -60,6 +61,72 @@
 
     public static final String SEARCH_PROVIDER_SETTINGS_KEY = "SEARCH_PROVIDER_PACKAGE_NAME";
 
+    /**
+     * Returns the package name for user configured search provider or from searchManager
+     * @param context
+     * @return String
+     */
+    @Nullable
+    public static String getSearchWidgetPackageName(@NonNull Context context) {
+        String providerPkg = Settings.Global.getString(context.getContentResolver(),
+                SEARCH_PROVIDER_SETTINGS_KEY);
+        if (providerPkg == null) {
+            SearchManager searchManager = context.getSystemService(SearchManager.class);
+            ComponentName componentName = searchManager.getGlobalSearchActivity();
+            if (componentName != null) {
+                providerPkg = searchManager.getGlobalSearchActivity().getPackageName();
+            }
+        }
+        return providerPkg;
+    }
+
+    /**
+     * returns it's AppWidgetProviderInfo using package name from getSearchWidgetPackageName
+     * @param context
+     * @return AppWidgetProviderInfo
+     */
+    @Nullable
+    public static AppWidgetProviderInfo getSearchWidgetProviderInfo(@NonNull Context context) {
+        String providerPkg = getSearchWidgetPackageName(context);
+        if (providerPkg == null) {
+            return null;
+        }
+
+        AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
+        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+        for (AppWidgetProviderInfo info :
+                appWidgetManager.getInstalledProvidersForPackage(providerPkg, null)) {
+            if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
+                if ((info.widgetCategory
+                        & AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX) != 0) {
+                    return info;
+                } else if (defaultWidgetForSearchPackage == null) {
+                    defaultWidgetForSearchPackage = info;
+                }
+            }
+        }
+        return defaultWidgetForSearchPackage;
+    }
+
+    /**
+     * returns componentName for searchWidget if package name is known.
+     */
+    @Nullable
+    public static ComponentName getSearchComponentName(@NonNull  Context context) {
+        AppWidgetProviderInfo providerInfo =
+                QsbContainerView.getSearchWidgetProviderInfo(context);
+        if (providerInfo != null) {
+            return providerInfo.provider;
+        } else {
+            String pkgName = QsbContainerView.getSearchWidgetPackageName(context);
+            if (pkgName != null) {
+                //we don't know the class name yet. we'll put the package name as placeholder
+                return new ComponentName(pkgName, pkgName);
+            }
+            return null;
+        }
+    }
+
     public QsbContainerView(Context context) {
         super(context);
     }
@@ -118,6 +185,7 @@
             mWrapper = new FrameLayout(getContext());
             // Only add the view when enabled
             if (isQsbEnabled()) {
+                mQsbWidgetHost.startListening();
                 mWrapper.addView(createQsb(mWrapper));
             }
             return mWrapper;
@@ -159,7 +227,8 @@
             }
 
             if (isWidgetBound) {
-                mQsb = (QsbWidgetHostView) mQsbWidgetHost.createView(context, widgetId, mWidgetInfo);
+                mQsb = (QsbWidgetHostView) mQsbWidgetHost.createView(context, widgetId,
+                        mWidgetInfo);
                 mQsb.setId(R.id.qsb_widget);
 
                 if (!isInPreviewMode()) {
@@ -167,7 +236,6 @@
                             .getAppWidgetOptions(widgetId), opts)) {
                         mQsb.updateAppWidgetOptions(opts);
                     }
-                    mQsbWidgetHost.startListening();
                 }
                 return mQsb;
             }
@@ -250,24 +318,6 @@
             return v;
         }
 
-        /**
-         * returns the package name string from global settings or from system search service.
-         *
-         * @return String (package name) or null if neither exist
-         */
-        @Nullable
-        protected String getSearchProviderPackageName() {
-            String providerPkg = Settings.Global.getString(getContext().getContentResolver(),
-                    SEARCH_PROVIDER_SETTINGS_KEY);
-            if (providerPkg == null) {
-                SearchManager searchManager = getContext().getSystemService(SearchManager.class);
-                ComponentName componentName = searchManager.getGlobalSearchActivity();
-                if (componentName != null) {
-                    providerPkg = searchManager.getGlobalSearchActivity().getPackageName();
-                }
-            }
-            return providerPkg;
-        }
 
         /**
          * Returns a widget with category {@link AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}
@@ -276,23 +326,7 @@
          * provided by the package.
          */
         protected AppWidgetProviderInfo getSearchWidgetProvider() {
-            String providerPkg = getSearchProviderPackageName();
-            if (providerPkg == null) {
-                return null;
-            }
-            AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
-            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getContext());
-            for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) {
-                if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
-                    if ((info.widgetCategory
-                            & AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX) != 0) {
-                        return info;
-                    } else if (defaultWidgetForSearchPackage == null) {
-                        defaultWidgetForSearchPackage = info;
-                    }
-                }
-            }
-            return defaultWidgetForSearchPackage;
+            return getSearchWidgetProviderInfo(getContext());
         }
     }
 
@@ -362,4 +396,5 @@
         }
         return true;
     }
+
 }
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index f9f5dc4..520598a 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -81,4 +81,6 @@
 
     public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824";
     public static final String NO_DRAG_TO_WORKSPACE = "b/138729456";
+    public static final String APP_NOT_DISABLED = "b/139891609";
+    public static final String ALL_APPS_UPON_RECENTS = "b/139941530";
 }
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index e7a2bca..cdda0f0 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -21,10 +21,10 @@
         mDevice = device;
     }
 
-    private void dumpViewHierarchy() {
+    private static void dumpViewHierarchy(UiDevice device) {
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();
         try {
-            mDevice.dumpWindowHierarchy(stream);
+            device.dumpWindowHierarchy(stream);
             stream.flush();
             stream.close();
             for (String line : stream.toString().split("\\r?\\n")) {
@@ -37,7 +37,11 @@
 
     @Override
     protected void failed(Throwable e, Description description) {
-        if (mDevice == null) return;
+        onError(mDevice, description, e);
+    }
+
+    public static void onError(UiDevice device, Description description, Throwable e) {
+        if (device == null) return;
         final String pathname = getInstrumentation().getTargetContext().
                 getFilesDir().getPath() + "/TestScreenshot-" + description.getMethodName()
                 + ".png";
@@ -45,15 +49,15 @@
                 ", screenshot will be saved to " + pathname +
                 ", track trace is below, UI object dump is further below:\n" +
                 Log.getStackTraceString(e));
-        dumpViewHierarchy();
+        dumpViewHierarchy(device);
 
         try {
-            final String dumpsysResult = mDevice.executeShellCommand(
+            final String dumpsysResult = device.executeShellCommand(
                     "dumpsys activity service TouchInteractionService");
             Log.d(TAG, "TouchInteractionService: " + dumpsysResult);
         } catch (IOException ex) {
         }
 
-        mDevice.takeScreenshot(new File(pathname));
+        device.takeScreenshot(new File(pathname));
     }
 }