Merge "Fix "Pause work apps" button in strange location" into udc-dev
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
index 3fddd9d..dc28c6a 100644
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher3.testing;
 
-import static com.android.launcher3.testing.shared.TestProtocol.VIEW_AND_ACTIVITY_LEAKS;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
@@ -25,10 +24,7 @@
 import android.content.Context;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.Process;
 import android.system.Os;
-import android.util.Log;
-import android.view.View;
 
 import androidx.annotation.Keep;
 import androidx.annotation.Nullable;
@@ -42,7 +38,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedList;
 import java.util.Map;
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
@@ -52,7 +47,6 @@
  * Class to handle requests from tests, including debug ones.
  */
 public class DebugTestInformationHandler extends TestInformationHandler {
-    private static LinkedList sLeaks;
     private static Collection<String> sEvents;
     private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks;
     private static final Map<Activity, Boolean> sActivities =
@@ -158,19 +152,6 @@
                 return response;
             }
 
-            case TestProtocol.REQUEST_VIEW_LEAK: {
-                if (sLeaks == null) sLeaks = new LinkedList();
-                Log.d(VIEW_AND_ACTIVITY_LEAKS, "forcefully leaking 2 views");
-                sLeaks.add(new View(mContext));
-                sLeaks.add(new View(mContext));
-                return response;
-            }
-
-            case TestProtocol.PRINT_VIEW_LEAK: {
-                Log.d(VIEW_AND_ACTIVITY_LEAKS, "(pid=" + Process.myPid() + ") sLeaks=" + sLeaks);
-                return response;
-            }
-
             case TestProtocol.REQUEST_START_EVENT_LOGGING: {
                 sEvents = new ArrayList<>();
                 TestLogging.setEventConsumer(
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 2aa0be6..1744b08 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -28,7 +28,6 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.view.View;
-import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
@@ -42,6 +41,7 @@
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.util.ResourceBasedOverride;
 import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.Snackbar;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
@@ -272,10 +272,8 @@
             String message = activityContext.getStringCache() != null
                     ? activityContext.getStringCache().disabledByAdminMessage
                     : mThumbnailView.getContext().getString(R.string.blocked_by_policy);
-            Toast.makeText(
-                    mThumbnailView.getContext(),
-                    message,
-                    Toast.LENGTH_LONG).show();
+
+            Snackbar.show(BaseActivity.fromContext(mThumbnailView.getContext()), message, null);
         }
 
         /** Called when the snapshot has updated its full screen drawing parameters. */
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 7b90ecb..32eadce 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -312,6 +312,7 @@
     @Test
     @ScreenRecord // b/242163205
     @PlatinumTest(focusArea = "launcher")
+    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testQuickSwitchToPreviousAppForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
         startTestActivity(2);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 0b75c45..28f378d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -518,11 +518,12 @@
         // TODO: move the SearchConfig to SearchState when new LauncherState is created.
         mBaseSearchConfig = new BaseSearchConfig();
 
+        setupViews();
+
         mAppWidgetManager = new WidgetManagerHelper(this);
         mAppWidgetHolder = createAppWidgetHolder();
         mAppWidgetHolder.startListening();
 
-        setupViews();
         mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
 
         boolean internalStateHandled = ACTIVITY_TRACKER.handleCreate(this);
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 1e3b003..2f7f51e 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -100,6 +100,7 @@
     private final UserCache mUserManager;
     private final InstantAppResolver mInstantAppResolver;
     private final IconProvider mIconProvider;
+    private final HandlerRunnable mCancelledRunnable;
 
     private final SparseArray<BitmapInfo> mWidgetCategoryBitmapInfos;
 
@@ -117,6 +118,10 @@
         mInstantAppResolver = InstantAppResolver.newInstance(mContext);
         mIconProvider = iconProvider;
         mWidgetCategoryBitmapInfos = new SparseArray<>();
+
+        mCancelledRunnable = new HandlerRunnable(
+                mWorkerHandler, () -> null, MAIN_EXECUTOR, c -> { });
+        mCancelledRunnable.cancel();
     }
 
     @Override
@@ -172,23 +177,30 @@
     public HandlerRunnable updateIconInBackground(final ItemInfoUpdateReceiver caller,
             final ItemInfoWithIcon info) {
         Preconditions.assertUIThread();
+        Supplier<ItemInfoWithIcon> task;
+        if (info instanceof AppInfo || info instanceof WorkspaceItemInfo) {
+            task = () -> {
+                getTitleAndIcon(info, false);
+                return info;
+            };
+        } else if (info instanceof PackageItemInfo pii) {
+            task = () -> {
+                getTitleAndIconForApp(pii, false);
+                return pii;
+            };
+        } else {
+            Log.i(TAG, "Icon update not supported for "
+                    + info == null ? "null" : info.getClass().getName());
+            return mCancelledRunnable;
+        }
+
         if (mPendingIconRequestCount <= 0) {
             MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
         }
         mPendingIconRequestCount++;
 
         HandlerRunnable<ItemInfoWithIcon> request = new HandlerRunnable<>(mWorkerHandler,
-                () -> {
-                    if (info instanceof AppInfo || info instanceof WorkspaceItemInfo) {
-                        getTitleAndIcon(info, false);
-                    } else if (info instanceof PackageItemInfo) {
-                        getTitleAndIconForApp((PackageItemInfo) info, false);
-                    }
-                    return info;
-                },
-                MAIN_EXECUTOR,
-                caller::reapplyItemInfo,
-                this::onIconRequestEnd);
+                task, MAIN_EXECUTOR, caller::reapplyItemInfo, this::onIconRequestEnd);
         Utilities.postAsyncCallback(mWorkerHandler, request);
         return request;
     }
diff --git a/src/com/android/launcher3/util/ViewOnDrawExecutor.java b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
index c2767be..fada4a3 100644
--- a/src/com/android/launcher3/util/ViewOnDrawExecutor.java
+++ b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
@@ -59,6 +59,7 @@
     private void attachObserver() {
         if (!mCompleted) {
             mAttachedView.getViewTreeObserver().addOnDrawListener(this);
+            mAttachedView.getRootView().invalidate();
         }
     }
 
diff --git a/src/com/android/launcher3/views/Snackbar.java b/src/com/android/launcher3/views/Snackbar.java
index 8d5838e..2460be1 100644
--- a/src/com/android/launcher3/views/Snackbar.java
+++ b/src/com/android/launcher3/views/Snackbar.java
@@ -65,9 +65,26 @@
         show(activity, labelStringRedId, NO_ID, onDismissed, null);
     }
 
+    /** Show a snackbar with just a label. */
+    public static <T extends Context & ActivityContext> void show(T activity, String labelString,
+            Runnable onDismissed) {
+        show(activity, labelString, NO_ID, onDismissed, null);
+    }
+
     /** Show a snackbar with a label and action. */
     public static <T extends Context & ActivityContext> void show(T activity, int labelStringResId,
             int actionStringResId, Runnable onDismissed, @Nullable Runnable onActionClicked) {
+        show(
+                activity,
+                activity.getResources().getString(labelStringResId),
+                actionStringResId,
+                onDismissed,
+                onActionClicked);
+    }
+
+    /** Show a snackbar with a label and action. */
+    public static <T extends Context & ActivityContext> void show(T activity, String labelString,
+            int actionStringResId, Runnable onDismissed, @Nullable Runnable onActionClicked) {
         closeOpenViews(activity, true, TYPE_SNACKBAR);
         Snackbar snackbar = new Snackbar(activity, null);
         // Set some properties here since inflated xml only contains the children.
@@ -105,8 +122,7 @@
                 : insets.bottom));
 
         TextView labelView = snackbar.findViewById(R.id.label);
-        String labelText = res.getString(labelStringResId);
-        labelView.setText(labelText);
+        labelView.setText(labelString);
 
         TextView actionView = snackbar.findViewById(R.id.action);
         float actionWidth;
@@ -127,7 +143,7 @@
             actionView.setVisibility(GONE);
         }
 
-        int totalContentWidth = (int) (labelView.getPaint().measureText(labelText) + actionWidth)
+        int totalContentWidth = (int) (labelView.getPaint().measureText(labelString) + actionWidth)
                 + labelView.getPaddingRight() + labelView.getPaddingLeft()
                 + padding * 2;
         if (totalContentWidth > params.width) {
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index b7c3aca..cbc537c 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -105,8 +105,6 @@
     public static final String REQUEST_WINDOW_INSETS = "window-insets";
     public static final String REQUEST_PID = "pid";
     public static final String REQUEST_FORCE_GC = "gc";
-    public static final String REQUEST_VIEW_LEAK = "view-leak";
-    public static final String PRINT_VIEW_LEAK = "print-leak";
     public static final String REQUEST_RECENT_TASKS_LIST = "recent-tasks-list";
     public static final String REQUEST_START_EVENT_LOGGING = "start-event-logging";
     public static final String REQUEST_GET_TEST_EVENTS = "get-test-events";
@@ -154,7 +152,6 @@
     public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
 
     public static final String PERMANENT_DIAG_TAG = "TaplTarget";
-    public static final String VIEW_AND_ACTIVITY_LEAKS = "b/260260325";
     public static final String WORK_TAB_MISSING = "b/243688989";
     public static final String TWO_TASKBAR_LONG_CLICKS = "b/262282528";
     public static final String WORKSPACE_LOADS_FOREVER = "b/267200150";
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2adfc98..c4f5da5 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1841,14 +1841,6 @@
         return testInfo != null ? testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) : null;
     }
 
-    public void produceViewLeak() {
-        getTestInfo(TestProtocol.REQUEST_VIEW_LEAK);
-    }
-
-    public void printViewLeak() {
-        getTestInfo(TestProtocol.PRINT_VIEW_LEAK);
-    }
-
     public ArrayList<ComponentName> getRecentTasks() {
         ArrayList<ComponentName> tasks = new ArrayList<>();
         ArrayList<String> components = getTestInfo(TestProtocol.REQUEST_RECENT_TASKS_LIST)