Merge "Search UI cleanup" into ub-launcher3-master
diff --git a/protos/launcher_trace.proto b/protos/launcher_trace.proto
index c6f3543..65fcfe5 100644
--- a/protos/launcher_trace.proto
+++ b/protos/launcher_trace.proto
@@ -28,4 +28,40 @@
 message TouchInteractionServiceProto {
 
     optional bool service_connected = 1;
+    optional OverviewComponentObserverProto overview_component_obvserver = 2;
+    optional InputConsumerProto input_consumer = 3;
+}
+
+message OverviewComponentObserverProto {
+
+    optional bool overview_activity_started = 1;
+    optional bool overview_activity_resumed = 2;
+}
+
+message InputConsumerProto {
+
+    optional string name = 1;
+    optional SwipeHandlerProto swipe_handler = 2;
+}
+
+message SwipeHandlerProto {
+
+    optional GestureStateProto gesture_state = 1;
+    optional bool is_recents_attached_to_app_window = 2;
+    optional int32 scroll_offset = 3;
+    // Swipe up progress from 0 (app) to 1 (overview); can be > 1 if swiping past overview.
+    optional float app_to_overview_progress = 4;
+}
+
+message GestureStateProto {
+
+    optional GestureEndTarget endTarget = 1 [default = UNSET];
+
+    enum GestureEndTarget {
+        UNSET = 0;
+        HOME = 1;
+        RECENTS = 2;
+        NEW_TASK = 3;
+        LAST_TASK = 4;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index dbf75fa..b43d63b 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -81,6 +81,8 @@
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.tracing.InputConsumerProto;
+import com.android.launcher3.tracing.SwipeHandlerProto;
 import com.android.launcher3.util.TraceHelper;
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.launcher3.util.WindowBounds;
@@ -92,6 +94,7 @@
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.util.InputConsumerProxy;
 import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.util.ProtoTracer;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.SurfaceTransactionApplier;
 import com.android.quickstep.util.TransformParams;
@@ -1608,6 +1611,27 @@
             }
             mTaskViewSimulator.apply(mTransformParams);
         }
+        ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate();
+    }
+
+    /**
+     * Used for winscope tracing, see launcher_trace.proto
+     * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
+     * @param inputConsumerProto The parent of this proto message.
+     */
+    public void writeToProto(InputConsumerProto.Builder inputConsumerProto) {
+        SwipeHandlerProto.Builder swipeHandlerProto = SwipeHandlerProto.newBuilder();
+
+        mGestureState.writeToProto(swipeHandlerProto);
+
+        swipeHandlerProto.setIsRecentsAttachedToAppWindow(
+                mAnimationFactory.isRecentsAttachedToAppWindow());
+        swipeHandlerProto.setScrollOffset(mRecentsView == null
+                ? 0
+                : mRecentsView.getScrollOffset());
+        swipeHandlerProto.setAppToOverviewProgress(mCurrentShift.value);
+
+        inputConsumerProto.setSwipeHandler(swipeHandlerProto);
     }
 
     public interface Factory {
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index d35e270..9089ae5 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -297,6 +297,10 @@
          * @param animate Whether to animate recents to/from its new attached state.
          */
         default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
+
+        default boolean isRecentsAttachedToAppWindow() {
+            return false;
+        }
     }
 
     class DefaultAnimationFactory implements AnimationFactory {
@@ -388,6 +392,11 @@
             fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start();
         }
 
+        @Override
+        public boolean isRecentsAttachedToAppWindow() {
+            return mIsAttachedToWindow;
+        }
+
         protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) {
             //  Scale down recents from being full screen to being in overview.
             RecentsView recentsView = activity.getOverviewPanel();
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 9c23c83..f788996 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -26,6 +26,8 @@
 import android.os.Build;
 
 import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.tracing.GestureStateProto;
+import com.android.launcher3.tracing.SwipeHandlerProto;
 import com.android.quickstep.util.ActiveGestureLog;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -46,19 +48,22 @@
      * Defines the end targets of a gesture and the associated state.
      */
     public enum GestureEndTarget {
-        HOME(true, LAUNCHER_STATE_HOME, false),
+        HOME(true, LAUNCHER_STATE_HOME, false, GestureStateProto.GestureEndTarget.HOME),
 
-        RECENTS(true, LAUNCHER_STATE_OVERVIEW, true),
+        RECENTS(true, LAUNCHER_STATE_OVERVIEW, true, GestureStateProto.GestureEndTarget.RECENTS),
 
-        NEW_TASK(false, LAUNCHER_STATE_BACKGROUND, true),
+        NEW_TASK(false, LAUNCHER_STATE_BACKGROUND, true,
+                GestureStateProto.GestureEndTarget.NEW_TASK),
 
-        LAST_TASK(false, LAUNCHER_STATE_BACKGROUND, true);
+        LAST_TASK(false, LAUNCHER_STATE_BACKGROUND, true,
+                GestureStateProto.GestureEndTarget.LAST_TASK);
 
-        GestureEndTarget(boolean isLauncher, int containerType,
-                boolean recentsAttachedToAppWindow) {
+        GestureEndTarget(boolean isLauncher, int containerType, boolean recentsAttachedToAppWindow,
+                GestureStateProto.GestureEndTarget protoEndTarget) {
             this.isLauncher = isLauncher;
             this.containerType = containerType;
             this.recentsAttachedToAppWindow = recentsAttachedToAppWindow;
+            this.protoEndTarget = protoEndTarget;
         }
 
         /** Whether the target is in the launcher activity. Implicitly, if the end target is going
@@ -68,6 +73,8 @@
         public final int containerType;
         /** Whether RecentsView should be attached to the window as we animate to this target */
         public final boolean recentsAttachedToAppWindow;
+        /** The GestureStateProto enum value, used for winscope tracing. See launcher_trace.proto */
+        public final GestureStateProto.GestureEndTarget protoEndTarget;
     }
 
     private static final String TAG = "GestureState";
@@ -345,4 +352,17 @@
         pw.println("  lastStartedTaskId=" + mLastStartedTaskId);
         pw.println("  isRecentsAnimationRunning=" + isRecentsAnimationRunning());
     }
+
+    /**
+     * Used for winscope tracing, see launcher_trace.proto
+     * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
+     * @param swipeHandlerProto The parent of this proto message.
+     */
+    public void writeToProto(SwipeHandlerProto.Builder swipeHandlerProto) {
+        GestureStateProto.Builder gestureStateProto = GestureStateProto.newBuilder();
+        gestureStateProto.setEndTarget(mEndTarget == null
+                ? GestureStateProto.GestureEndTarget.UNSET
+                : mEndTarget.protoEndTarget);
+        swipeHandlerProto.setGestureState(gestureStateProto);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 67711c0..0b2a057 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -21,6 +21,9 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
+import com.android.launcher3.tracing.InputConsumerProto;
+import com.android.launcher3.tracing.TouchInteractionServiceProto;
+
 @TargetApi(Build.VERSION_CODES.O)
 public interface InputConsumer {
 
@@ -116,4 +119,21 @@
         }
         return name.toString();
     }
+
+    /**
+     * Used for winscope tracing, see launcher_trace.proto
+     * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
+     * @param serviceProto The parent of this proto message.
+     */
+    default void writeToProto(TouchInteractionServiceProto.Builder serviceProto) {
+        InputConsumerProto.Builder inputConsumerProto = InputConsumerProto.newBuilder();
+        inputConsumerProto.setName(getName());
+        writeToProtoInternal(inputConsumerProto);
+        serviceProto.setInputConsumer(inputConsumerProto);
+    }
+
+    /**
+     * @see #writeToProto - allows subclasses to write additional info to the proto.
+     */
+    default void writeToProtoInternal(InputConsumerProto.Builder inputConsumerProto) {}
 }
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index b1b9396..9f7871a 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -35,6 +35,7 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.systemui.shared.system.LatencyTrackerCompat;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
@@ -174,6 +175,9 @@
                 return;
             }
 
+            InteractionJankMonitorWrapper.begin(
+                    InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH, 2000 /* ms timout */);
+
             // Otherwise, start overview.
             mListener = mActivityInterface.createActivityInitListener(this::onActivityReady);
             mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 07f838b..49feef0 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -35,6 +35,8 @@
 import android.content.pm.ResolveInfo;
 import android.util.SparseIntArray;
 
+import com.android.launcher3.tracing.OverviewComponentObserverProto;
+import com.android.launcher3.tracing.TouchInteractionServiceProto;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.systemui.shared.system.PackageManagerWrapper;
 
@@ -262,4 +264,17 @@
         pw.println("  overviewIntent=" + mOverviewIntent);
         pw.println("  homeIntent=" + mCurrentHomeIntent);
     }
+
+    /**
+     * Used for winscope tracing, see launcher_trace.proto
+     * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
+     * @param serviceProto The parent of this proto message.
+     */
+    public void writeToProto(TouchInteractionServiceProto.Builder serviceProto) {
+        OverviewComponentObserverProto.Builder overviewComponentObserver =
+                OverviewComponentObserverProto.newBuilder();
+        overviewComponentObserver.setOverviewActivityStarted(mActivityInterface.isStarted());
+        overviewComponentObserver.setOverviewActivityResumed(mActivityInterface.isResumed());
+        serviceProto.setOverviewComponentObvserver(overviewComponentObserver);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 7299c38..5520ef7 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -44,6 +44,7 @@
 
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
@@ -58,6 +59,7 @@
 import com.android.quickstep.views.TaskThumbnailView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
 /**
@@ -135,6 +137,8 @@
             RemoteAnimationTargetCompat[] appTargets,
             RemoteAnimationTargetCompat[] wallpaperTargets, DepthController depthController,
             PendingAnimation out) {
+        boolean isQuickSwitch = v.isEndQuickswitchCuj();
+        v.setEndQuickswitchCuj(false);
 
         SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
         final RemoteAnimationTargets targets =
@@ -232,10 +236,19 @@
             });
         }
 
-        out.addListener(new AnimatorListenerAdapter() {
+        out.addListener(new AnimationSuccessListener() {
+            @Override
+            public void onAnimationSuccess(Animator animator) {
+                if (isQuickSwitch) {
+                    InteractionJankMonitorWrapper.end(
+                            InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
+                }
+            }
+
             @Override
             public void onAnimationEnd(Animator animation) {
                 targets.release();
+                super.onAnimationEnd(animation);
             }
         });
 
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index d3c4f55..eebb0de 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -893,6 +893,12 @@
         TouchInteractionServiceProto.Builder serviceProto =
             TouchInteractionServiceProto.newBuilder();
         serviceProto.setServiceConnected(true);
+
+        if (mOverviewComponentObserver != null) {
+            mOverviewComponentObserver.writeToProto(serviceProto);
+        }
+        mConsumer.writeToProto(serviceProto);
+
         proto.setTouchInteractionService(serviceProto);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
index 67a15a7..8da2fd3 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
@@ -4,6 +4,7 @@
 
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.tracing.InputConsumerProto;
 import com.android.quickstep.InputConsumer;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
@@ -53,4 +54,9 @@
         mDelegate.onMotionEvent(event);
         event.recycle();
     }
+
+    @Override
+    public void writeToProtoInternal(InputConsumerProto.Builder inputConsumerProto) {
+        mDelegate.writeToProtoInternal(inputConsumerProto);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 35dbee9..82f489f 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -51,6 +51,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.tracing.InputConsumerProto;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.AbsSwipeUpHandler;
@@ -478,4 +479,11 @@
     public boolean allowInterceptByParent() {
         return !mPassedPilferInputSlop || mGestureState.hasState(STATE_OVERSCROLL_WINDOW_CREATED);
     }
+
+    @Override
+    public void writeToProtoInternal(InputConsumerProto.Builder inputConsumerProto) {
+        if (mInteractionHandler != null) {
+            mInteractionHandler.writeToProto(inputConsumerProto);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7a8e11d..65a445b 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -539,6 +539,9 @@
     @Override
     protected void onWindowVisibilityChanged(int visibility) {
         super.onWindowVisibilityChanged(visibility);
+        if (visibility == GONE && ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+            finishRecentsAnimation(true /* toRecents */, null);
+        }
         updateTaskStackListenerState();
     }
 
@@ -1292,19 +1295,26 @@
     }
 
     public void showNextTask() {
-        TaskView runningTaskView = getRunningTaskView();
+        final TaskView runningTaskView = getRunningTaskView();
+        final TaskView targetTask;
+
         if (runningTaskView == null) {
             // Launch the first task
             if (getTaskViewCount() > 0) {
-                getTaskViewAt(0).launchTask(true);
+                targetTask = getTaskViewAt(0);
+            } else {
+                return;
             }
         } else {
-            if (getNextTaskView() != null) {
-                getNextTaskView().launchTask(true);
+            final TaskView nextTask = getNextTaskView();
+            if (nextTask != null) {
+                targetTask = nextTask;
             } else {
-                runningTaskView.launchTask(true);
+                targetTask = runningTaskView;
             }
         }
+        targetTask.setEndQuickswitchCuj(true);
+        targetTask.launchTask(true);
     }
 
     public void setRunningTaskIconScaledDown(boolean isScaledDown) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 686f878..54a793c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -189,6 +189,8 @@
     private CancellableTask mThumbnailLoadRequest;
     private CancellableTask mIconLoadRequest;
 
+    private boolean mEndQuickswitchCuj;
+
     // Order in which the footers appear. Lower order appear below higher order.
     public static final int INDEX_DIGITAL_WELLBEING_TOAST = 0;
     private final FooterWrapper[] mFooters = new FooterWrapper[2];
@@ -807,6 +809,14 @@
         return false;
     }
 
+    public boolean isEndQuickswitchCuj() {
+        return mEndQuickswitchCuj;
+    }
+
+    public void setEndQuickswitchCuj(boolean endQuickswitchCuj) {
+        mEndQuickswitchCuj = endQuickswitchCuj;
+    }
+
     private static final class TaskOutlineProvider extends ViewOutlineProvider {
 
         private final int mMarginTop;
diff --git a/res/layout/search_result_icon_row.xml b/res/layout/search_result_icon_row.xml
index 5ecc0c2..ef3c8b2 100644
--- a/res/layout/search_result_icon_row.xml
+++ b/res/layout/search_result_icon_row.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Projectza
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
diff --git a/res/layout/search_result_play_item.xml b/res/layout/search_result_play_item.xml
index 4e82eaf..cdb793c 100644
--- a/res/layout/search_result_play_item.xml
+++ b/res/layout/search_result_play_item.xml
@@ -67,7 +67,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="start|center_vertical"
-        android:background="?android:attr/selectableItemBackground"
         android:text="@string/search_action_try_now">
     </Button>
 
diff --git a/res/layout/search_result_suggest.xml b/res/layout/search_result_suggest.xml
index c5d96f0..a3227cb 100644
--- a/res/layout/search_result_suggest.xml
+++ b/res/layout/search_result_suggest.xml
@@ -12,27 +12,24 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.views.SearchResultSuggestRow xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/TextHeadline"
-    android:id="@+id/section_title"
-    android:background="?android:attr/selectableItemBackground"
+<com.android.launcher3.views.SearchResultIconRow xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto"
+    style="@style/BaseIcon"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:gravity="center_vertical"
-    android:padding="4dp"
-    android:minHeight="48dp"
+    android:orientation="horizontal"
+    android:gravity="start|center_vertical"
+    android:textAlignment="viewStart"
     android:textColor="?android:attr/textColorPrimary"
-    android:textSize="14sp">
+    android:textSize="16sp"
+    android:padding="@dimen/dynamic_grid_edge_margin"
+    launcher:iconDisplay="hero_app"
+    android:drawableTint="?android:attr/textColorPrimary"
+    launcher:customIcon="@drawable/ic_allapps_search"
+    launcher:iconSizeOverride="24dp"
+    launcher:matchTextInsetWithQuery="true"
+    launcher:layoutHorizontal="true"
+    android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding"
+    >
 
-    <TextView
-        android:id="@+id/title"
-        style="@style/TextTitle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:paddingStart="8dp"
-        android:layout_marginBottom="4dp"
-        android:textColor="?android:attr/textColorPrimary"
-        android:textSize="14sp" />
-
-</com.android.launcher3.views.SearchResultSuggestRow>
\ No newline at end of file
+</com.android.launcher3.views.SearchResultIconRow>
\ No newline at end of file
diff --git a/res/layout/search_section_title.xml b/res/layout/search_section_title.xml
index 9419015..c541631 100644
--- a/res/layout/search_section_title.xml
+++ b/res/layout/search_section_title.xml
@@ -18,6 +18,7 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:fontFamily="@style/TextHeadline"
+    android:textStyle="bold"
     android:padding="4dp"
     android:textColor="?android:attr/textColorPrimary"
     android:textSize="14sp" />
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index acb8221..6b0f300 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -69,6 +69,13 @@
         <attr name="folderDotColor" />
     </declare-styleable>
 
+    <declare-styleable name="SearchResultIconRow">
+        <attr name="customIcon" format="reference" />
+        <attr name="matchTextInsetWithQuery" format="boolean" />
+    </declare-styleable>
+
+
+
     <declare-styleable name="ShadowInfo">
         <attr name="ambientShadowColor" format="color" />
         <attr name="ambientShadowBlur" format="dimension" />
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 1e5a9e4..817d028 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -627,7 +627,7 @@
     /**
      * Sets the icon for this view based on the layout direction.
      */
-    private void setIcon(Drawable icon) {
+    protected void setIcon(Drawable icon) {
         if (mIsIconVisible) {
             applyCompoundDrawables(icon);
         }
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 4195a05..0c488a6 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -68,16 +68,16 @@
     public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
             new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
 
-        @Override
-        public Float get(AllAppsTransitionController controller) {
-            return controller.mProgress;
-        }
+                @Override
+                public Float get(AllAppsTransitionController controller) {
+                    return controller.mProgress;
+                }
 
-        @Override
-        public void setValue(AllAppsTransitionController controller, float progress) {
-            controller.setProgress(progress);
-        }
-    };
+                @Override
+                public void setValue(AllAppsTransitionController controller, float progress) {
+                    controller.setProgress(progress);
+                }
+            };
 
     private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 0;
 
@@ -133,7 +133,6 @@
      * in xml-based animations which also handle updating the appropriate UI.
      *
      * @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
-     *
      * @see #setState(LauncherState)
      * @see #setStateWithAnimation(LauncherState, StateAnimationConfig, PendingAnimation)
      */
@@ -238,7 +237,7 @@
             mInsetController = new AllAppsInsetTransitionController(mShiftRange, mAppsView);
             mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
                     View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+                            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         }
     }
 
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 4175280..58b0a87 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -156,10 +156,14 @@
             "ENABLE_DATABASE_RESTORE", true,
             "Enable database restore when new restore session is created");
 
-    public static final BooleanFlag ENABLE_UNIVERSAL_SMARTSPACE = getDebugFlag(
-            "ENABLE_UNIVERSAL_SMARTSPACE", false,
+    public static final BooleanFlag ENABLE_SMARTSPACE_UNIVERSAL = getDebugFlag(
+            "ENABLE_SMARTSPACE_UNIVERSAL", false,
             "Replace Smartspace with a version rendered by System UI.");
 
+    public static final BooleanFlag ENABLE_SMARTSPACE_BLUECHIP = getDebugFlag(
+            "ENABLE_SMARTSPACE_BLUECHIP", false,
+            "Replace Smartspace with the Bluechip version. Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
+
     public static final BooleanFlag ENABLE_SYSTEM_VELOCITY_PROVIDER = getDebugFlag(
             "ENABLE_SYSTEM_VELOCITY_PROVIDER", true,
             "Use system VelocityTracker's algorithm for motion pause detection.");
diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index dd322d9..91337ba 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -96,8 +96,6 @@
             launcher.getItemOnClickListener().onClick(view);
         });
         mBubbleTextView.setOnLongClickListener(new HeroItemDragHandler(getContext(), this));
-        setLayoutParams(
-                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, grid.allAppsCellHeightPx));
 
 
         mDeepShortcutTextViews[0] = findViewById(R.id.shortcut_0);
diff --git a/src/com/android/launcher3/views/SearchResultIconRow.java b/src/com/android/launcher3/views/SearchResultIconRow.java
index 6438d1d..c73eeae 100644
--- a/src/com/android/launcher3/views/SearchResultIconRow.java
+++ b/src/com/android/launcher3/views/SearchResultIconRow.java
@@ -22,16 +22,19 @@
 import android.app.RemoteAction;
 import android.content.Context;
 import android.content.pm.ShortcutInfo;
+import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
 import android.util.AttributeSet;
+import android.widget.EditText;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
 import com.android.launcher3.allapps.search.AllAppsSearchBarController;
 import com.android.launcher3.icons.BitmapInfo;
@@ -53,25 +56,51 @@
         AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
 
     private final Object[] mTargetInfo = createTargetInfo();
+    private final int mCustomIconResId;
+    private final boolean mMatchesInset;
+
     private ShortcutInfo mShortcutInfo;
     private AllAppsSearchPlugin mPlugin;
     private AdapterItemWithPayload<SearchTarget> mAdapterItem;
 
 
     public SearchResultIconRow(@NonNull Context context) {
-        super(context);
+        this(context, null, 0);
     }
 
     public SearchResultIconRow(@NonNull Context context,
             @Nullable AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public SearchResultIconRow(@NonNull Context context, @Nullable AttributeSet attrs,
             int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.SearchResultIconRow, defStyleAttr, 0);
+        mCustomIconResId = a.getResourceId(R.styleable.SearchResultIconRow_customIcon, 0);
+        mMatchesInset = a.getBoolean(R.styleable.SearchResultIconRow_matchTextInsetWithQuery,
+                false);
+
+        a.recycle();
     }
 
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        Launcher launcher = Launcher.getLauncher(getContext());
+        if (mMatchesInset && launcher.getAppsView() != null && getParent() != null) {
+            EditText editText = launcher.getAppsView().getSearchUiManager().getEditText();
+            if (editText != null) {
+                int counterOffset = getIconSize() + getCompoundDrawablePadding() / 2;
+                setPadding(editText.getLeft() - counterOffset, getPaddingTop(),
+                        getPaddingRight(), getPaddingBottom());
+            }
+        }
+    }
+
+
     @Override
     public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
         if (mAdapterItem != null) {
@@ -98,10 +127,12 @@
         WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext());
         applyFromWorkspaceItem(workspaceItemInfo);
         LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
-        MODEL_EXECUTOR.execute(() -> {
-            launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
-            reapplyItemInfoAsync(workspaceItemInfo);
-        });
+        if (!loadIconFromResource()) {
+            MODEL_EXECUTOR.execute(() -> {
+                launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo);
+                reapplyItemInfoAsync(workspaceItemInfo);
+            });
+        }
     }
 
     private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start,
@@ -109,27 +140,36 @@
         RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start);
 
         applyFromRemoteActionInfo(itemInfo);
-        UI_HELPER_EXECUTOR.post(() -> {
-            // If the Drawable from the remote action is not AdaptiveBitmap, styling will not work.
-            try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
-                Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext());
-                BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
-                        Build.VERSION.SDK_INT);
+        if (!loadIconFromResource()) {
+            UI_HELPER_EXECUTOR.post(() -> {
+                // If the Drawable from the remote action is not AdaptiveBitmap, styling will not
+                // work.
+                try (LauncherIcons li = LauncherIcons.obtain(getContext())) {
+                    Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext());
+                    BitmapInfo bitmap = li.createBadgedIconBitmap(d, itemInfo.user,
+                            Build.VERSION.SDK_INT);
 
-                if (useIconToBadge) {
-                    BitmapInfo placeholder = li.createIconBitmap(
-                            itemInfo.getRemoteAction().getTitle().toString().substring(0, 1),
-                            bitmap.color);
-                    itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap);
-                } else {
-                    itemInfo.bitmap = bitmap;
+                    if (useIconToBadge) {
+                        BitmapInfo placeholder = li.createIconBitmap(
+                                itemInfo.getRemoteAction().getTitle().toString().substring(0, 1),
+                                bitmap.color);
+                        itemInfo.bitmap = li.badgeBitmap(placeholder.icon, bitmap);
+                    } else {
+                        itemInfo.bitmap = bitmap;
+                    }
+                    reapplyItemInfoAsync(itemInfo);
                 }
-                reapplyItemInfoAsync(itemInfo);
-            }
-        });
+            });
+        }
 
     }
 
+    private boolean loadIconFromResource() {
+        if (mCustomIconResId == 0) return false;
+        setIcon(Launcher.getLauncher(getContext()).getDrawable(mCustomIconResId));
+        return true;
+    }
+
     void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) {
         MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon));
     }
diff --git a/src/com/android/launcher3/views/SearchResultSuggestRow.java b/src/com/android/launcher3/views/SearchResultSuggestRow.java
deleted file mode 100644
index 6543c76..0000000
--- a/src/com/android/launcher3/views/SearchResultSuggestRow.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.views;
-
-import static com.android.systemui.plugins.shared.SearchTarget.ItemType.SUGGEST;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
-import com.android.launcher3.allapps.search.AllAppsSearchBarController;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.RemoteActionItemInfo;
-import com.android.launcher3.touch.ItemClickHandler;
-import com.android.systemui.plugins.AllAppsSearchPlugin;
-import com.android.systemui.plugins.shared.SearchTarget;
-import com.android.systemui.plugins.shared.SearchTargetEvent;
-
-/**
- * A view representing a fallback search suggestion row.
- */
-public class SearchResultSuggestRow extends LinearLayout implements
-        View.OnClickListener, AllAppsSearchBarController.PayloadResultHandler<SearchTarget> {
-
-    private final Object[] mTargetInfo = createTargetInfo();
-    private AllAppsSearchPlugin mPlugin;
-    private AdapterItemWithPayload<SearchTarget> mAdapterItem;
-    private TextView mTitle;
-
-
-    public SearchResultSuggestRow(@NonNull Context context) {
-        super(context);
-    }
-
-    public SearchResultSuggestRow(@NonNull Context context,
-            @Nullable AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public SearchResultSuggestRow(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mTitle = findViewById(R.id.title);
-        setOnClickListener(this);
-    }
-    @Override
-    public void applyAdapterInfo(AdapterItemWithPayload<SearchTarget> adapterItemWithPayload) {
-        mAdapterItem = adapterItemWithPayload;
-        SearchTarget payload = adapterItemWithPayload.getPayload();
-        mPlugin = adapterItemWithPayload.getPlugin();
-
-        if (payload.mRemoteAction != null) {
-            RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(payload.mRemoteAction,
-                    payload.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN),
-                    payload.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START));
-            setTag(itemInfo);
-        }
-        showIfAvailable(mTitle, payload.mRemoteAction.getTitle().toString());
-        setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT));
-        adapterItemWithPayload.setSelectionHandler(this::handleSelection);
-    }
-
-    @Override
-    public Object[] getTargetInfo() {
-        return mTargetInfo;
-    }
-
-    private void handleSelection(int eventType) {
-        ItemInfo itemInfo = (ItemInfo) getTag();
-        Launcher launcher = Launcher.getLauncher(getContext());
-
-        if (!(itemInfo instanceof  RemoteActionItemInfo)) return;
-
-        RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo;
-        ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo);
-        SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SUGGEST, eventType);
-        searchTargetEvent.bundle = new Bundle();
-        searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction();
-        searchTargetEvent.bundle.putBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START,
-                remoteItemInfo.shouldStartInLauncher());
-        searchTargetEvent.bundle.putString(SearchTarget.REMOTE_ACTION_TOKEN,
-                remoteItemInfo.getToken());
-
-        if (mPlugin != null) {
-            mPlugin.notifySearchTargetEvent(searchTargetEvent);
-        }
-    }
-
-    @Override
-    public void onClick(View view) {
-        handleSelection(SearchTargetEvent.SELECT);
-    }
-
-    private void showIfAvailable(TextView view, @Nullable String string) {
-        System.out.println("Plugin suggest string:" + string);
-        if (TextUtils.isEmpty(string)) {
-            view.setVisibility(GONE);
-        } else {
-            System.out.println("Plugin suggest string:" + string);
-            view.setVisibility(VISIBLE);
-            view.setText(string);
-        }
-    }
-}