Merge "Tapl: AllApps: ensuring a minimal vertical size of an icon" into ub-launcher3-qt-future-dev
diff --git a/go/quickstep/res/values/override.xml b/go/quickstep/res/values/override.xml
index 7636fb3..bb267a3 100644
--- a/go/quickstep/res/values/override.xml
+++ b/go/quickstep/res/values/override.xml
@@ -22,5 +22,7 @@
   <string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
 
   <string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+
+  <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
 </resources>
 
diff --git a/quickstep/recents_ui_overrides/res/values/override.xml b/quickstep/recents_ui_overrides/res/values/override.xml
index 1ddd3f5..ed3ba92 100644
--- a/quickstep/recents_ui_overrides/res/values/override.xml
+++ b/quickstep/recents_ui_overrides/res/values/override.xml
@@ -24,5 +24,7 @@
   <string name="app_launch_tracker_class" translatable="false">com.android.launcher3.appprediction.PredictionAppTracker</string>
 
   <string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+
+  <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherAppPredictionExtension</string>
 </resources>
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 1a59770..9c66107 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -25,12 +25,16 @@
 import android.content.ComponentName;
 import android.content.Context;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.AppInfo;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
+import com.android.launcher3.ItemInfo;
 import com.android.launcher3.ItemInfoWithIcon;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.LauncherStateManager.StateListener;
 import com.android.launcher3.Utilities;
@@ -39,12 +43,14 @@
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
 import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.MainThreadInitializedObject;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.IntStream;
 
 /**
  * Handler responsible to updating the UI due to predicted apps changes. Operations:
@@ -322,6 +328,30 @@
         return mCurrentState;
     }
 
+    /**
+     * Fill in predicted_rank field based on app prediction.
+     * Only applicable when {@link ItemInfo#itemType} is one of the followings:
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
+     */
+    public static void fillInPredictedRank(
+            @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
+        final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
+        if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
+                || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+                && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+                && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
+            return;
+        }
+        final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+        final List<ComponentKeyMapper> predictedApps = manager.getCurrentState().apps;
+        IntStream.range(0, predictedApps.size())
+                .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+                .findFirst()
+                .ifPresent((rank) -> target.predictedRank = rank);
+    }
+
     public static class PredictionState {
 
         public boolean isEnabled;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
new file mode 100644
index 0000000..b251f9e
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.logging;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.appprediction.PredictionUiStateManager;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+
+/**
+ * This class handles AOSP MetricsLogger function calls and logging around
+ * quickstep interactions and app launches.
+ */
+@SuppressWarnings("unused")
+public class UserEventDispatcherAppPredictionExtension extends UserEventDispatcherExtension {
+
+    public static final int ALL_APPS_PREDICTION_TIPS = 2;
+
+    private static final String TAG = "UserEventDispatcher";
+
+    public UserEventDispatcherAppPredictionExtension(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onFillInLogContainerData(
+            @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target,
+            @NonNull LauncherLogProto.Target targetParent) {
+        PredictionUiStateManager.fillInPredictedRank(itemInfo, target);
+    }
+}
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 5c4d6d8..292eaaa 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -21,8 +21,6 @@
     <!-- Activity which blocks home gesture -->
     <string name="gesture_blocking_activity" translatable="false"></string>
 
-    <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
-
     <string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
 
     <string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
diff --git a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
index 4a11601..9ca7f23 100644
--- a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
+++ b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
@@ -20,10 +20,10 @@
 
 import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
 import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
 import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
 import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
 import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
 
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 9b75b43..ed08c02 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -44,6 +44,7 @@
 public class LoggerUtils {
     private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
     private static final String UNKNOWN = "UNKNOWN";
+    private static final int DEFAULT_PREDICTED_RANK = -100;
 
     public static String getFieldName(int value, Class c) {
         SparseArray<String> cache;
@@ -168,17 +169,17 @@
 
     public static Target newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver) {
         Target t = newTarget(Target.Type.ITEM);
-
         switch (info.itemType) {
             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                 t.itemType = (instantAppResolver != null && info instanceof AppInfo
                         && instantAppResolver.isInstantApp(((AppInfo) info)) )
                         ? ItemType.WEB_APP
                         : ItemType.APP_ICON;
-                t.predictedRank = -100; // Never assigned
+                t.predictedRank = DEFAULT_PREDICTED_RANK;
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                 t.itemType = ItemType.SHORTCUT;
+                t.predictedRank = DEFAULT_PREDICTED_RANK;
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                 t.itemType = ItemType.FOLDER_ICON;
@@ -188,6 +189,7 @@
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                 t.itemType = ItemType.DEEPSHORTCUT;
+                t.predictedRank = DEFAULT_PREDICTED_RANK;
                 break;
         }
         return t;
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 21ca74e..7b06d3b 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -35,6 +35,7 @@
 import android.util.Log;
 import android.view.View;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.DropTarget;
@@ -96,17 +97,23 @@
      * Fills in the container data on the given event if the given view is not null.
      * @return whether container data was added.
      */
-    public static boolean fillInLogContainerData(LauncherLogProto.LauncherEvent event, @Nullable View v) {
+    public boolean fillInLogContainerData(LauncherLogProto.LauncherEvent event, @Nullable View v) {
         // Fill in grid(x,y), pageIndex of the child and container type of the parent
         LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(v);
         if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
             return false;
         }
-        ItemInfo itemInfo = (ItemInfo) v.getTag();
-        provider.fillInLogContainerData(v, itemInfo, event.srcTarget[0], event.srcTarget[1]);
+        final ItemInfo itemInfo = (ItemInfo) v.getTag();
+        final Target target = event.srcTarget[0];
+        final Target targetParent = event.srcTarget[1];
+        onFillInLogContainerData(itemInfo, target, targetParent);
+        provider.fillInLogContainerData(v, itemInfo, target, targetParent);
         return true;
     }
 
+    protected void onFillInLogContainerData(
+            @NonNull ItemInfo itemInfo, @NonNull Target target, @NonNull Target targetParent) { }
+
     private boolean mSessionStarted;
     private long mElapsedContainerMillis;
     private long mElapsedSessionMillis;
diff --git a/src/com/android/launcher3/util/ViewPool.java b/src/com/android/launcher3/util/ViewPool.java
index 8af048d..5b33f18 100644
--- a/src/com/android/launcher3/util/ViewPool.java
+++ b/src/com/android/launcher3/util/ViewPool.java
@@ -21,12 +21,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import com.android.launcher3.util.ViewPool.Reusable;
-
 import androidx.annotation.AnyThread;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
+import com.android.launcher3.util.ViewPool.Reusable;
+
 /**
  * Utility class to maintain a pool of reusable views.
  * During initialization, views are inflated on the background thread.
@@ -58,14 +58,18 @@
         Preconditions.assertUIThread();
         Handler handler = new Handler();
 
+        // LayoutInflater is not thread save as it maintains a global variable 'mConstructorArgs'.
+        // Create a different copy to use on the background thread.
+        LayoutInflater inflater = mInflater.cloneInContext(mInflater.getContext());
+
         // Inflate views on a non looper thread. This allows us to catch errors like calling
         // "new Handler()" in constructor easily.
         new Thread(() -> {
             for (int i = 0; i < initialSize; i++) {
-                T view = inflateNewView();
+                T view = inflateNewView(inflater);
                 handler.post(() -> addToPool(view));
             }
-        }).start();
+        }, "ViewPool-init").start();
     }
 
     @UiThread
@@ -94,12 +98,12 @@
             mCurrentSize--;
             return (T) mPool[mCurrentSize];
         }
-        return inflateNewView();
+        return inflateNewView(mInflater);
     }
 
     @AnyThread
-    private T inflateNewView() {
-        return (T) mInflater.inflate(mLayoutId, mParent, false);
+    private T inflateNewView(LayoutInflater inflater) {
+        return (T) inflater.inflate(mLayoutId, mParent, false);
     }
 
     /**
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 709822b..98a0a01 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -349,6 +349,7 @@
      * Custom shortcuts are replaced by deep shortcuts after api 25.
      */
     @Test
+    @Ignore   // b/143725213
     @PortraitLandscape
     public void testDragCustomShortcut() {
         mLauncher.getWorkspace().openAllWidgets()