Merge "Enable variable size thumbnail for large screen" into sc-dev
diff --git a/quickstep/protos_overrides/launcher_atom_extension.proto b/quickstep/protos_overrides/launcher_atom_extension.proto
index 2766acf..6253b41 100644
--- a/quickstep/protos_overrides/launcher_atom_extension.proto
+++ b/quickstep/protos_overrides/launcher_atom_extension.proto
@@ -31,4 +31,5 @@
 
 // Represents on-device search result container.
 message DeviceSearchResultContainer{
+  optional int32 query_length = 1;
 }
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
index f7d5f45..4c44479 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.search;
 
+import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
 import static com.android.launcher3.model.data.SearchActionItemInfo.FLAG_BADGE_WITH_PACKAGE;
 import static com.android.launcher3.model.data.SearchActionItemInfo.FLAG_PRIMARY_ICON_FROM_TITLE;
 import static com.android.launcher3.search.SearchTargetUtil.BUNDLE_EXTRA_PRIMARY_ICON_FROM_TITLE;
@@ -49,7 +50,6 @@
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.BitmapRenderer;
 import com.android.launcher3.icons.LauncherIcons;
-import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
 import com.android.launcher3.logger.LauncherAtomExtensions.DeviceSearchResultContainer;
 import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers;
 import com.android.launcher3.model.data.AppInfo;
@@ -81,7 +81,7 @@
     private static final int BITMAP_CROP_MASK_COLOR = 0xff424242;
 
     private final Launcher mLauncher;
-
+    private final SearchSessionTracker mSearchSessionTracker;
     private String mTargetId;
     private Consumer<ItemInfoWithIcon> mOnItemInfoChanged;
 
@@ -97,6 +97,7 @@
     public SearchResultIcon(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mLauncher = Launcher.getLauncher(getContext());
+        mSearchSessionTracker = SearchSessionTracker.getInstance(getContext());
     }
 
     private boolean mLongPressSupported;
@@ -113,8 +114,8 @@
     }
 
     /**
-     * Applies {@link SearchTarget} to view. registers a consumer after a corresponding
-     * {@link ItemInfoWithIcon} is created
+     * Applies {@link SearchTarget} to view. registers a consumer after a corresponding {@link
+     * ItemInfoWithIcon} is created
      */
     public void apply(SearchTarget searchTarget, List<SearchTarget> inlineItems,
             Consumer<ItemInfoWithIcon> cb) {
@@ -146,11 +147,10 @@
         SearchActionItemInfo itemInfo = new SearchActionItemInfo(searchAction.getIcon(),
                 searchTarget.getPackageName(), searchTarget.getUserHandle(),
                 searchAction.getTitle()) {
-            // Workaround to log ItemInfo with DeviceSearchResultContainer without
-            // updating ItemInfo.container field.
             @Override
-            public ContainerInfo getContainerInfo() {
-                return buildDeviceSearchResultContainer();
+            protected ExtendedContainers getExtendedContainer() {
+                return ExtendedContainers.newBuilder()
+                        .setDeviceSearchResultContainer(buildDeviceSearchResultContainer()).build();
             }
         };
         itemInfo.setIntent(searchAction.getIntent());
@@ -254,14 +254,13 @@
         AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
         AppInfo appInfo = new AppInfo(
                 appsStore.getApp(new ComponentKey(componentName, userHandle))) {
-            // Workaround to log ItemInfo with DeviceSearchResultContainer without
-            // updating ItemInfo.container field.
             @Override
-            public ContainerInfo getContainerInfo() {
-                return buildDeviceSearchResultContainer();
+            protected ExtendedContainers getExtendedContainer() {
+                return ExtendedContainers.newBuilder()
+                        .setDeviceSearchResultContainer(buildDeviceSearchResultContainer()).build();
             }
         };
-
+        appInfo.container = EXTENDED_CONTAINERS;
         if (appInfo == null) {
             setVisibility(GONE);
             return;
@@ -272,13 +271,13 @@
 
     private void prepareUsingShortcutInfo(ShortcutInfo shortcutInfo) {
         WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(shortcutInfo, getContext()) {
-            // Workaround to log ItemInfo with DeviceSearchResultContainer without
-            // updating ItemInfo.container field.
             @Override
-            public ContainerInfo getContainerInfo() {
-                return buildDeviceSearchResultContainer();
+            protected ExtendedContainers getExtendedContainer() {
+                return ExtendedContainers.newBuilder()
+                        .setDeviceSearchResultContainer(buildDeviceSearchResultContainer()).build();
             }
         };
+        workspaceItemInfo.container = EXTENDED_CONTAINERS;
         notifyItemInfoChanged(workspaceItemInfo);
         LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext());
         MODEL_EXECUTOR.execute(() -> {
@@ -317,13 +316,10 @@
         }
     }
 
-    private static ContainerInfo buildDeviceSearchResultContainer() {
-        return ContainerInfo.newBuilder().setExtendedContainers(
-                ExtendedContainers
-                        .newBuilder()
-                        .setDeviceSearchResultContainer(
-                                DeviceSearchResultContainer
-                                        .newBuilder()))
-                .build();
+    private DeviceSearchResultContainer buildDeviceSearchResultContainer() {
+        return mSearchSessionTracker.getQueryLength()
+                .map(queryLength -> DeviceSearchResultContainer.newBuilder()
+                        .setQueryLength(queryLength))
+                .orElse(DeviceSearchResultContainer.newBuilder()).build();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java b/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java
index 3079965..97a72bb 100644
--- a/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java
+++ b/quickstep/src/com/android/launcher3/search/SearchSessionTracker.java
@@ -15,9 +15,10 @@
  */
 package com.android.launcher3.search;
 
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
 import android.app.search.Query;
 import android.app.search.SearchSession;
-import android.app.search.SearchTarget;
 import android.app.search.SearchTargetEvent;
 import android.content.Context;
 import android.util.Log;
@@ -27,7 +28,7 @@
 
 import com.android.launcher3.util.MainThreadInitializedObject;
 
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import java.util.Optional;
 
 /**
  * A singleton class to track and report search events back to SearchSession
@@ -63,6 +64,10 @@
         mQuery = query;
     }
 
+    public Optional<Integer> getQueryLength() {
+        return Optional.ofNullable(mQuery).map(Query::getInput).map(String::length);
+    }
+
     /**
      * Send the user event handling back to the {@link SearchSession} object.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java
index 4dc051a..082343e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java
@@ -57,6 +57,7 @@
 
     protected void init() {
         mLauncher.getDragController().addDragListener(mDragListener);
+        onHotseatUpdated();
     }
 
     protected void cleanup() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentsController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentsController.java
index 9d4e000..4256d2b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentsController.java
@@ -50,6 +50,8 @@
     // The current background requests to load the task icons
     private CancellableTask[] mIconLoadRequests = new CancellableTask[mNumRecentIcons];
 
+    private boolean mIsAlive;
+
     public TaskbarRecentsController(BaseQuickstepLauncher launcher,
             TaskbarController.TaskbarRecentsControllerCallbacks taskbarCallbacks) {
         mLauncher = launcher;
@@ -58,11 +60,13 @@
     }
 
     protected void init() {
+        mIsAlive = true;
         TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackChangeListener);
         reloadRecentTasksIfNeeded();
     }
 
     protected void cleanup() {
+        mIsAlive = false;
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
                 mTaskStackChangeListener);
         cancelAllPendingIconLoadTasks();
@@ -84,7 +88,9 @@
     }
 
     private void onRecentTasksChanged(ArrayList<Task> tasks) {
-        mTaskbarCallbacks.updateRecentItems(tasks);
+        if (mIsAlive) {
+            mTaskbarCallbacks.updateRecentItems(tasks);
+        }
     }
 
     /**
diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties
index 4e811f3..0ac997f 100644
--- a/robolectric_tests/config/robolectric.properties
+++ b/robolectric_tests/config/robolectric.properties
@@ -1,4 +1,4 @@
-sdk=29
+sdk=30
 shadows= \
     com.android.launcher3.shadows.LShadowAppPredictionManager \
     com.android.launcher3.shadows.LShadowAppWidgetManager \
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index fe423ed..be270397 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -171,6 +171,9 @@
         public static final int CONTAINER_SETTINGS = -108;
         public static final int CONTAINER_TASKSWITCHER = -109;
 
+        // Represents any of the extended containers implemented in non-AOSP variants.
+        public static final int EXTENDED_CONTAINERS = -200;
+
         public static final String containerToString(int container) {
             switch (container) {
                 case CONTAINER_DESKTOP: return "desktop";
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 3851ab0..00ac12f 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -26,6 +26,7 @@
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
+import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
@@ -54,6 +55,7 @@
 import com.android.launcher3.logger.LauncherAtom.Shortcut;
 import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer;
 import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer;
+import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers;
 import com.android.launcher3.model.ModelWriter;
 import com.android.launcher3.util.ContentWriter;
 
@@ -403,12 +405,23 @@
                 return ContainerInfo.newBuilder()
                         .setTaskSwitcherContainer(TaskSwitcherContainer.getDefaultInstance())
                         .build();
-
+            case EXTENDED_CONTAINERS:
+                return ContainerInfo.newBuilder()
+                        .setExtendedContainers(getExtendedContainer())
+                        .build();
         }
         return ContainerInfo.getDefaultInstance();
     }
 
     /**
+     * Returns non-AOSP container wrapped by {@link ExtendedContainers} object. Should be overridden
+     * by build variants.
+     */
+    protected ExtendedContainers getExtendedContainer() {
+        return ExtendedContainers.getDefaultInstance();
+    }
+
+    /**
      * Returns shallow copy of the object.
      */
     public ItemInfo makeShallowCopy() {
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index 8469569..25355c9 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.model.data;
 
+import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
+
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
@@ -45,6 +47,7 @@
             CharSequence title) {
         this.user = user == null ? Process.myUserHandle() : user;
         this.title = title;
+        this.container = EXTENDED_CONTAINERS;
         mFallbackPackageName = packageName;
         mIcon = icon;
     }
@@ -55,6 +58,7 @@
         mFallbackPackageName = info.mFallbackPackageName;
         mFlags = info.mFlags;
         title = info.title;
+        this.container = EXTENDED_CONTAINERS;
     }
 
     /**