Merge "Adding support for generating manachrome icon from a colored icon" into tm-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/LauncherLifecycleListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java
similarity index 78%
rename from quickstep/src/com/android/launcher3/LauncherLifecycleListener.java
rename to quickstep/src/com/android/launcher3/LauncherInitListener.java
index 82c646d..28bd701 100644
--- a/quickstep/src/com/android/launcher3/LauncherLifecycleListener.java
+++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -16,23 +16,19 @@
 package com.android.launcher3;
 
 import android.animation.AnimatorSet;
-import android.annotation.Nullable;
 import android.annotation.TargetApi;
 import android.os.Build;
 import android.os.CancellationSignal;
 import android.view.RemoteAnimationTarget;
 
 import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.util.ActivityLifecycleListener;
+import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.RemoteAnimationProvider;
 
 import java.util.function.BiPredicate;
 
-/**
- * {@link ActivityLifecycleListener} for the in-launcher recents.
- */
 @TargetApi(Build.VERSION_CODES.P)
-public class LauncherLifecycleListener extends ActivityLifecycleListener<Launcher> {
+public class LauncherInitListener extends ActivityInitListener<Launcher> {
 
     private RemoteAnimationProvider mRemoteAnimationProvider;
 
@@ -40,16 +36,13 @@
      * @param onInitListener a callback made when the activity is initialized. The callback should
      *                       return true to continue receiving callbacks (ie. for if the activity is
      *                       recreated).
-     * @param onDestroyListener a callback made when the activity is destroyed.
      */
-    public LauncherLifecycleListener(
-            @Nullable BiPredicate<Launcher, Boolean> onInitListener,
-            @Nullable Runnable onDestroyListener) {
-        super(onInitListener, onDestroyListener, Launcher.ACTIVITY_TRACKER);
+    public LauncherInitListener(BiPredicate<Launcher, Boolean> onInitListener) {
+        super(onInitListener, Launcher.ACTIVITY_TRACKER);
     }
 
     @Override
-    public boolean handleActivityReady(Launcher launcher, boolean alreadyOnHome) {
+    public boolean handleInit(Launcher launcher, boolean alreadyOnHome) {
         if (mRemoteAnimationProvider != null) {
             QuickstepTransitionManager appTransitionManager =
                     ((QuickstepLauncher) launcher).getAppTransitionManager();
@@ -75,7 +68,7 @@
             }, cancellationSignal);
         }
         launcher.deferOverlayCallbacksUntilNextResumeOrStop();
-        return super.handleActivityReady(launcher, alreadyOnHome);
+        return super.handleInit(launcher, alreadyOnHome);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index e41841a..3d8ffc4 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -50,7 +50,6 @@
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.LAUNCHER_DESTROYED;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
 import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -114,7 +113,7 @@
 import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
 import com.android.quickstep.util.ActiveGestureErrorDetector;
 import com.android.quickstep.util.ActiveGestureLog;
-import com.android.quickstep.util.ActivityLifecycleListener;
+import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.util.InputConsumerProxy;
 import com.android.quickstep.util.InputProxyHandlerFactory;
@@ -160,7 +159,7 @@
 
     protected final BaseActivityInterface<S, T> mActivityInterface;
     protected final InputConsumerProxy mInputConsumerProxy;
-    protected final ActivityLifecycleListener mActivityInitListener;
+    protected final ActivityInitListener mActivityInitListener;
     // Callbacks to be made once the recents animation starts
     private final ArrayList<Runnable> mRecentsAnimationStartCallbacks = new ArrayList<>();
     private final OnScrollChangedListener mOnRecentsScrollListener = this::onRecentsViewScroll;
@@ -330,8 +329,7 @@
             InputConsumerController inputConsumer) {
         super(context, deviceState, gestureState);
         mActivityInterface = gestureState.getActivityInterface();
-        mActivityInitListener = mActivityInterface.createActivityLifecycleListener(
-                this::onActivityInit, this::onActivityDestroy);
+        mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
         mInputConsumerProxy =
                 new InputConsumerProxy(context, /* rotationSupplier = */ () -> {
                     if (mRecentsView == null) {
@@ -522,11 +520,6 @@
         return true;
     }
 
-    private void onActivityDestroy() {
-        ActiveGestureLog.INSTANCE.addLog("Launcher activity destroyed", LAUNCHER_DESTROYED);
-        onGestureCancelled();
-    }
-
     /**
      * Return true if the window should be translated horizontally if the recents view scrolls
      */
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 5523518..274b686 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -60,7 +60,7 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.views.ScrimView;
-import com.android.quickstep.util.ActivityLifecycleListener;
+import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -123,17 +123,8 @@
     public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
             boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
 
-    /**
-     * Creates a activity listener for activity initialized and/or destroyed. One or both of these
-     * listeners must be provided.
-     *
-     * @param onInitListener a callback made when the activity is initialized. The callback should
-     *                       return true to continue receiving callbacks (ie. for if the activity is
-     *                       recreated).
-     * @param onDestroyListener a callback made when the activity is destroyed.
-     */
-    public abstract ActivityLifecycleListener createActivityLifecycleListener(
-            @Nullable Predicate<Boolean> onInitListener, @Nullable Runnable onDestroyListener);
+    public abstract ActivityInitListener createActivityInitListener(
+            Predicate<Boolean> onInitListener);
 
     /**
      * Sets a callback to be run when an activity launch happens while launcher is not yet resumed.
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index a658566..ae9fb0b 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -36,7 +36,7 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.quickstep.GestureState.GestureEndTarget;
 import com.android.quickstep.fallback.RecentsState;
-import com.android.quickstep.util.ActivityLifecycleListener;
+import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.views.RecentsView;
 
@@ -88,12 +88,10 @@
     }
 
     @Override
-    public ActivityLifecycleListener createActivityLifecycleListener(
-            @Nullable Predicate<Boolean> onInitListener, @Nullable Runnable onDestroyListener) {
-        return new ActivityLifecycleListener<>(
-                (activity, alreadyOnHome) -> onInitListener.test(alreadyOnHome),
-                onDestroyListener,
-                RecentsActivity.ACTIVITY_TRACKER);
+    public ActivityInitListener createActivityInitListener(
+            Predicate<Boolean> onInitListener) {
+        return new ActivityInitListener<>((activity, alreadyOnHome) ->
+                onInitListener.test(alreadyOnHome), RecentsActivity.ACTIVITY_TRACKER);
     }
 
     @Nullable
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index cb54d2e..9ff9416 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -37,7 +37,7 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAnimUtils;
-import com.android.launcher3.LauncherLifecycleListener;
+import com.android.launcher3.LauncherInitListener;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.statehandlers.DepthController;
@@ -49,7 +49,7 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.NavigationMode;
 import com.android.quickstep.GestureState.GestureEndTarget;
-import com.android.quickstep.util.ActivityLifecycleListener;
+import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
@@ -136,10 +136,9 @@
     }
 
     @Override
-    public ActivityLifecycleListener createActivityLifecycleListener(
-            @Nullable Predicate<Boolean> onInitListener, @Nullable Runnable onDestroyListener) {
-        return new LauncherLifecycleListener((activity, alreadyOnHome) ->
-                onInitListener.test(alreadyOnHome), onDestroyListener);
+    public ActivityInitListener createActivityInitListener(Predicate<Boolean> onInitListener) {
+        return new LauncherInitListener((activity, alreadyOnHome) ->
+                onInitListener.test(alreadyOnHome));
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 0fdd8b5..60065fb 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -37,7 +37,7 @@
         ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION, FINISH_RECENTS_ANIMATION,
         CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION,
         CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
-        FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED,
+        FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER,
 
         /**
          * These GestureEvents are specifically associated to state flags that get set in
@@ -162,13 +162,6 @@
                                         + "before/without setting end target to new task",
                                 writer);
                         break;
-                    case LAUNCHER_DESTROYED:
-                        errorDetected |= printErrorIfTrue(
-                                true,
-                                prefix,
-                                /* errorMessage= */ "Launcher destroyed mid-gesture",
-                                writer);
-                        break;
                     case STATE_GESTURE_COMPLETED:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.MOTION_UP),
diff --git a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
new file mode 100644
index 0000000..aeec36f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.util.ActivityTracker;
+import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
+
+import java.util.function.BiPredicate;
+
+public class ActivityInitListener<T extends BaseActivity> implements
+        SchedulerCallback<T> {
+
+    private BiPredicate<T, Boolean> mOnInitListener;
+    private final ActivityTracker<T> mActivityTracker;
+
+    private boolean mIsRegistered = false;
+
+    /**
+     * @param onInitListener a callback made when the activity is initialized. The callback should
+     *                       return true to continue receiving callbacks (ie. for if the activity is
+     *                       recreated).
+     */
+    public ActivityInitListener(BiPredicate<T, Boolean> onInitListener,
+            ActivityTracker<T> tracker) {
+        mOnInitListener = onInitListener;
+        mActivityTracker = tracker;
+    }
+
+    @Override
+    public final boolean init(T activity, boolean alreadyOnHome) {
+        if (!mIsRegistered) {
+            // Don't receive any more updates
+            return false;
+        }
+        return handleInit(activity, alreadyOnHome);
+    }
+
+    protected boolean handleInit(T activity, boolean alreadyOnHome) {
+        return mOnInitListener.test(activity, alreadyOnHome);
+    }
+
+    /**
+     * Registers the activity-created listener. If the activity is already created, then the
+     * callback provided in the constructor will be called synchronously.
+     */
+    public void register() {
+        mIsRegistered = true;
+        mActivityTracker.registerCallback(this);
+    }
+
+    /**
+     * After calling this, we won't {@link #init} even when the activity is ready.
+     */
+    public void unregister() {
+        mActivityTracker.unregisterCallback(this);
+        mIsRegistered = false;
+        mOnInitListener = null;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/util/ActivityLifecycleListener.java b/quickstep/src/com/android/quickstep/util/ActivityLifecycleListener.java
deleted file mode 100644
index 1edf188..0000000
--- a/quickstep/src/com/android/quickstep/util/ActivityLifecycleListener.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2022 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.util;
-
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BaseActivity;
-import com.android.launcher3.util.ActivityTracker;
-import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
-
-import java.util.function.BiPredicate;
-
-/**
- * Listener for activity initialized and/or destroyed.
- */
-public class ActivityLifecycleListener<T extends BaseActivity> implements
-        SchedulerCallback<T> {
-
-    private static final String TAG = "ActivityLifecycleListener";
-
-    @Nullable private final BiPredicate<T, Boolean> mOnInitListener;
-    @Nullable private final Runnable mOnDestroyListener;
-    private final ActivityTracker<T> mActivityTracker;
-
-    private boolean mIsRegistered = false;
-
-    /**
-     * One or both of {@code onInitListener} and {@code onInitListener} must be provided, otherwise
-     * the created instance will effectively be a no-op.
-     *
-     * @param onInitListener a callback made when the activity is initialized. The callback should
-     *                       return true to continue receiving callbacks (ie. for if the activity is
-     *                       recreated).
-     * @param onDestroyListener a callback made when the activity is destroyed.
-     */
-    public ActivityLifecycleListener(
-            @Nullable BiPredicate<T, Boolean> onInitListener,
-            @Nullable Runnable onDestroyListener,
-            ActivityTracker<T> tracker) {
-        if (onInitListener == null && onDestroyListener == null) {
-            throw new IllegalArgumentException("Both listeners cannot be null");
-        }
-        mOnInitListener = onInitListener;
-        mOnDestroyListener = onDestroyListener;
-        mActivityTracker = tracker;
-    }
-
-    @Override
-    public final boolean onActivityReady(T activity, boolean alreadyOnHome) {
-        if (!mIsRegistered) {
-            // Don't receive any more updates
-            return false;
-        }
-        return handleActivityReady(activity, alreadyOnHome);
-    }
-
-    protected boolean handleActivityReady(T activity, boolean alreadyOnHome) {
-        if (mOnInitListener == null) {
-            Log.e(TAG, "Cannot handle init: init listener is null", new Exception());
-            return false;
-        }
-        return mOnInitListener.test(activity, alreadyOnHome);
-    }
-
-    @Override
-    public void onActivityDestroyed() {
-        if (mOnDestroyListener == null) {
-            Log.e(TAG, "Cannot clean up: destroy listener is null", new Exception());
-            return;
-        }
-        mOnDestroyListener.run();
-    }
-
-    /**
-     * Registers the activity-created listener. If the activity is already created, then the
-     * callback provided in the constructor will be called synchronously.
-     */
-    public void register() {
-        mIsRegistered = true;
-        mActivityTracker.registerCallback(this, getType());
-    }
-
-    /**
-     * After calling this, we won't call {@link #onActivityReady} even when the activity is ready.
-     */
-    public void unregister() {
-        mActivityTracker.unregisterCallback(this, getType());
-        mIsRegistered = false;
-    }
-
-    private int getType() {
-        return mOnInitListener != null && mOnDestroyListener != null
-                ? ActivityTracker.TYPE_BOTH
-                : (mOnInitListener != null
-                        ? ActivityTracker.TYPE_INIT
-                        : ActivityTracker.TYPE_DESTROY);
-    }
-}
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index f7600ff..47bef7b 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -63,6 +63,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -167,6 +168,7 @@
 
     // b/143488140
     //@NavigationModeSwitch
+    @Ignore
     @Test
     public void goToOverviewFromHome() {
         mDevice.pressHome();
@@ -178,6 +180,7 @@
 
     // b/143488140
     //@NavigationModeSwitch
+    @Ignore
     @Test
     public void goToOverviewFromApp() {
         startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
@@ -213,6 +216,7 @@
 
     // b/143488140
     //@NavigationModeSwitch
+    @Ignore
     @Test
     public void testOverview() {
         startAppFast(getAppPackageName());
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index 401b967..df5303f 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -24,6 +24,7 @@
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -56,6 +57,7 @@
         eventProcessor.finishIteration();
     }
 
+    @Ignore
     @Test
     @NavigationModeSwitch
     public void testStressPressHome() {
@@ -68,6 +70,7 @@
         }
     }
 
+    @Ignore
     @Test
     @NavigationModeSwitch
     public void testStressSwipeToOverview() {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index cc561c6..9a2fcc0 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -44,6 +44,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -224,6 +225,7 @@
         return launcher.<RecentsView>getOverviewPanel().getBottomRowTaskCountForTablet();
     }
 
+    @Ignore
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -236,6 +238,7 @@
                 isInState(() -> LauncherState.OVERVIEW));
     }
 
+    @Ignore
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -363,6 +366,7 @@
         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
     }
 
+    @Ignore
     @Test
     @PortraitLandscape
     public void testOverviewForTablet() throws Exception {
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index efdd5e1..55ede6c 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -31,7 +31,6 @@
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Pair;
 import android.util.Patterns;
 import android.util.Xml;
 
@@ -45,7 +44,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.qsb.QsbContainerView;
 import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 
@@ -76,19 +75,16 @@
 
     static AutoInstallsLayout get(Context context, LauncherWidgetHolder appWidgetHolder,
             LayoutParserCallback callback) {
-        Pair<String, Resources> customizationApkInfo = PackageManagerHelper.findSystemApk(
-                ACTION_LAUNCHER_CUSTOMIZATION, context.getPackageManager());
-        if (customizationApkInfo == null) {
+        Partner partner = Partner.get(context.getPackageManager(), ACTION_LAUNCHER_CUSTOMIZATION);
+        if (partner == null) {
             return null;
         }
-        String pkg = customizationApkInfo.first;
-        Resources targetRes = customizationApkInfo.second;
         InvariantDeviceProfile grid = LauncherAppState.getIDP(context);
 
         // Try with grid size and hotseat count
         String layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES_WITH_HOSTEAT,
                 grid.numColumns, grid.numRows, grid.numDatabaseHotseatIcons);
-        int layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
+        int layoutId = partner.getXmlResId(layoutName);
 
         // Try with only grid size
         if (layoutId == 0) {
@@ -96,21 +92,21 @@
                     + " not found. Trying layout without hosteat");
             layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES,
                     grid.numColumns, grid.numRows);
-            layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
+            layoutId = partner.getXmlResId(layoutName);
         }
 
         // Try the default layout
         if (layoutId == 0) {
             Log.d(TAG, "Formatted layout: " + layoutName + " not found. Trying the default layout");
-            layoutId = targetRes.getIdentifier(LAYOUT_RES, "xml", pkg);
+            layoutId = partner.getXmlResId(LAYOUT_RES);
         }
 
         if (layoutId == 0) {
-            Log.e(TAG, "Layout definition not found in package: " + pkg);
+            Log.e(TAG, "Layout definition not found in package: " + partner.getPackageName());
             return null;
         }
-        return new AutoInstallsLayout(context, appWidgetHolder, callback, targetRes, layoutId,
-                TAG_WORKSPACE);
+        return new AutoInstallsLayout(context, appWidgetHolder, callback, partner.getResources(),
+                layoutId, TAG_WORKSPACE);
     }
 
     // Object Tags
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index c707df0..ec29b29 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -16,12 +16,15 @@
 
 package com.android.launcher3;
 
+import android.os.Handler;
+import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 
 /**
- * Utility class to handle tripper long press on a view with custom timeout and stylus event
+ * Utility class to handle tripper long press or right click on a view with custom timeout and
+ * stylus event
  */
 public class CheckLongPressHelper {
 
@@ -34,6 +37,7 @@
     private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
 
     private boolean mHasPerformedLongPress;
+    private boolean mIsInMouseRightClick;
 
     private Runnable mPendingCheckForLongPress;
 
@@ -59,6 +63,26 @@
                 // start fresh on touch down.
                 cancelLongPress();
 
+                // Mouse right click should immediately trigger a long press
+                if (isMouseRightClickDownOrMove(ev)) {
+                    mIsInMouseRightClick = true;
+                    triggerLongPress();
+                    final Handler handler = mView.getHandler();
+                    if (handler != null) {
+                        // Send an ACTION_UP to end this click gesture to avoid user dragging with
+                        // mouse's right button. Note that we need to call
+                        // {@link Handler#postAtFrontOfQueue()} instead of {@link View#post()} to
+                        // make sure ACTION_UP is sent before any ACTION_MOVE if user is dragging.
+                        final MotionEvent actionUpEvent = MotionEvent.obtain(ev);
+                        actionUpEvent.setAction(MotionEvent.ACTION_UP);
+                        handler.postAtFrontOfQueue(() -> {
+                            mView.getRootView().dispatchTouchEvent(actionUpEvent);
+                            actionUpEvent.recycle();
+                        });
+                    }
+                    break;
+                }
+
                 postCheckForLongPress();
                 if (isStylusButtonPressed(ev)) {
                     triggerLongPress();
@@ -70,7 +94,8 @@
                 cancelLongPress();
                 break;
             case MotionEvent.ACTION_MOVE:
-                if (!Utilities.pointInView(mView, ev.getX(), ev.getY(), mSlop)) {
+                if (mIsInMouseRightClick
+                        || !Utilities.pointInView(mView, ev.getX(), ev.getY(), mSlop)) {
                     cancelLongPress();
                 } else if (mPendingCheckForLongPress != null && isStylusButtonPressed(ev)) {
                     // Only trigger long press if it has not been cancelled before
@@ -98,9 +123,10 @@
     }
 
     /**
-     * Cancels any pending long press
+     * Cancels any pending long press and right click
      */
     public void cancelLongPress() {
+        mIsInMouseRightClick = false;
         mHasPerformedLongPress = false;
         clearCallbacks();
     }
@@ -150,4 +176,14 @@
         return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
                 && event.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
     }
+
+    /**
+     * Detect ACTION_DOWN or ACTION_MOVE from mouse right button. Note that we cannot detect
+     * ACTION_UP from mouse's right button because, in that case,
+     * {@link MotionEvent#getButtonState()} returns 0 for any mouse button (right, middle, right).
+     */
+    private static boolean isMouseRightClickDownOrMove(MotionEvent event) {
+        return event.isFromSource(InputDevice.SOURCE_MOUSE)
+                && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0);
+    }
 }
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index af13bea..c69ae4d 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -19,6 +19,7 @@
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 
@@ -51,6 +52,9 @@
     private static final String ATTR_SHORTCUT_ID = "shortcutId";
     private static final String ATTR_PACKAGE_NAME = "packageName";
 
+    public static final String RES_PARTNER_FOLDER = "partner_folder";
+    public static final String RES_PARTNER_DEFAULT_LAYOUT = "partner_default_layout";
+
     // TODO: Remove support for this broadcast, instead use widget options to send bind time options
     private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
             "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
@@ -278,10 +282,9 @@
             // Folder contents come from an external XML resource
             final Partner partner = Partner.get(mPackageManager);
             if (partner != null) {
-                final Resources partnerRes = partner.getResources();
-                final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
-                        "xml", partner.getPackageName());
+                final int resId = partner.getXmlResId(RES_PARTNER_FOLDER);
                 if (resId != 0) {
+                    final Resources partnerRes = partner.getResources();
                     final XmlPullParser partnerParser = partnerRes.getXml(resId);
                     beginDocument(partnerParser, TAG_FOLDER);
 
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 1f97535..594d7cb 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -60,6 +60,7 @@
 import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.WindowBounds;
 import com.android.launcher3.util.window.WindowManagerProxy;
@@ -112,6 +113,11 @@
     static final int INDEX_TWO_PANEL_PORTRAIT = 2;
     static final int INDEX_TWO_PANEL_LANDSCAPE = 3;
 
+    /** These resources are used to override the device profile  */
+    private static final String RES_GRID_NUM_ROWS = "grid_num_rows";
+    private static final String RES_GRID_NUM_COLUMNS = "grid_num_columns";
+    private static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp";
+
     /**
      * Number of icons per row and column in the workspace.
      */
@@ -567,8 +573,24 @@
      */
     private void applyPartnerDeviceProfileOverrides(Context context, DisplayMetrics dm) {
         Partner p = Partner.get(context.getPackageManager());
-        if (p != null) {
-            p.applyInvariantDeviceProfileOverrides(this, dm);
+        if (p == null) {
+            return;
+        }
+        try {
+            int numRows = p.getIntValue(RES_GRID_NUM_ROWS, -1);
+            int numColumns = p.getIntValue(RES_GRID_NUM_COLUMNS, -1);
+            float iconSizePx = p.getDimenValue(RES_GRID_ICON_SIZE_DP, -1);
+
+            if (numRows > 0 && numColumns > 0) {
+                this.numRows = numRows;
+                this.numColumns = numColumns;
+            }
+            if (iconSizePx > 0) {
+                this.iconSize[InvariantDeviceProfile.INDEX_DEFAULT] =
+                        Utilities.dpiFromPx(iconSizePx, dm.densityDpi);
+            }
+        } catch (Resources.NotFoundException ex) {
+            Log.e(TAG, "Invalid Partner grid resource!", ex);
         }
     }
 
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index d002c2b..8ddbbaa 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT;
 import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
 import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
@@ -34,7 +35,6 @@
 import android.content.OperationApplicationException;
 import android.content.SharedPreferences;
 import android.content.pm.ProviderInfo;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.SQLException;
@@ -70,6 +70,7 @@
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.NoLocaleSQLiteHelper;
 import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.widget.LauncherWidgetHolder;
 
@@ -544,13 +545,11 @@
             }
             if (loader == null) {
                 final Partner partner = Partner.get(getContext().getPackageManager());
-                if (partner != null && partner.hasDefaultLayout()) {
-                    final Resources partnerRes = partner.getResources();
-                    int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
-                            "xml", partner.getPackageName());
+                if (partner != null) {
+                    int workspaceResId = partner.getXmlResId(RES_PARTNER_DEFAULT_LAYOUT);
                     if (workspaceResId != 0) {
                         loader = new DefaultLayoutParser(getContext(), widgetHolder,
-                                mOpenHelper, partnerRes, workspaceResId);
+                                mOpenHelper, partner.getResources(), workspaceResId);
                     }
                 }
             }
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
deleted file mode 100644
index 2e27f32..0000000
--- a/src/com/android/launcher3/Partner.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import static com.android.launcher3.util.PackageManagerHelper.findSystemApk;
-
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.Pair;
-
-import java.io.File;
-
-/**
- * Utilities to discover and interact with partner customizations. There can
- * only be one set of customizations on a device, and it must be bundled with
- * the system.
- */
-public class Partner {
-
-    static final String TAG = "Launcher.Partner";
-
-    /** Marker action used to discover partner */
-    private static final String
-            ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";
-
-    public static final String RES_FOLDER = "partner_folder";
-    public static final String RES_WALLPAPERS = "partner_wallpapers";
-    public static final String RES_DEFAULT_LAYOUT = "partner_default_layout";
-
-    public static final String RES_DEFAULT_WALLPAPER_HIDDEN = "default_wallpapper_hidden";
-    public static final String RES_SYSTEM_WALLPAPER_DIR = "system_wallpaper_directory";
-
-    public static final String RES_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow";
-
-    /** These resources are used to override the device profile  */
-    public static final String RES_GRID_NUM_ROWS = "grid_num_rows";
-    public static final String RES_GRID_NUM_COLUMNS = "grid_num_columns";
-    public static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp";
-
-    /**
-     * Find and return partner details, or {@code null} if none exists.
-     */
-    public static synchronized Partner get(PackageManager pm) {
-        Pair<String, Resources> apkInfo = findSystemApk(ACTION_PARTNER_CUSTOMIZATION, pm);
-        return apkInfo != null ? new Partner(apkInfo.first, apkInfo.second) : null;
-    }
-
-    private final String mPackageName;
-    private final Resources mResources;
-
-    private Partner(String packageName, Resources res) {
-        mPackageName = packageName;
-        mResources = res;
-    }
-
-    public String getPackageName() {
-        return mPackageName;
-    }
-
-    public Resources getResources() {
-        return mResources;
-    }
-
-    public boolean hasDefaultLayout() {
-        int defaultLayout = getResources().getIdentifier(Partner.RES_DEFAULT_LAYOUT,
-                "xml", getPackageName());
-        return defaultLayout != 0;
-    }
-
-    public boolean hasFolder() {
-        int folder = getResources().getIdentifier(Partner.RES_FOLDER,
-                "xml", getPackageName());
-        return folder != 0;
-    }
-
-    public boolean hideDefaultWallpaper() {
-        int resId = getResources().getIdentifier(RES_DEFAULT_WALLPAPER_HIDDEN, "bool",
-                getPackageName());
-        return resId != 0 && getResources().getBoolean(resId);
-    }
-
-    public File getWallpaperDirectory() {
-        int resId = getResources().getIdentifier(RES_SYSTEM_WALLPAPER_DIR, "string",
-                getPackageName());
-        return (resId != 0) ? new File(getResources().getString(resId)) : null;
-    }
-
-    public boolean requiresFirstRunFlow() {
-        int resId = getResources().getIdentifier(RES_REQUIRE_FIRST_RUN_FLOW, "bool",
-                getPackageName());
-        return resId != 0 && getResources().getBoolean(resId);
-    }
-
-    public void applyInvariantDeviceProfileOverrides(InvariantDeviceProfile inv, DisplayMetrics dm) {
-        int numRows = -1;
-        int numColumns = -1;
-        float iconSize = -1;
-
-        try {
-            int resId = getResources().getIdentifier(RES_GRID_NUM_ROWS,
-                    "integer", getPackageName());
-            if (resId > 0) {
-                numRows = getResources().getInteger(resId);
-            }
-
-            resId = getResources().getIdentifier(RES_GRID_NUM_COLUMNS,
-                    "integer", getPackageName());
-            if (resId > 0) {
-                numColumns = getResources().getInteger(resId);
-            }
-
-            resId = getResources().getIdentifier(RES_GRID_ICON_SIZE_DP,
-                    "dimen", getPackageName());
-            if (resId > 0) {
-                int px = getResources().getDimensionPixelSize(resId);
-                iconSize = Utilities.dpiFromPx((float) px, dm.densityDpi);
-            }
-        } catch (Resources.NotFoundException ex) {
-            Log.e(TAG, "Invalid Partner grid resource!", ex);
-            return;
-        }
-
-        if (numRows > 0 && numColumns > 0) {
-            inv.numRows = numRows;
-            inv.numColumns = numColumns;
-        }
-
-        if (iconSize > 0) {
-            inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT] = iconSize;
-        }
-    }
-}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index aa7e5d1..5cab817 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -89,14 +89,6 @@
             getDebugFlag("ENABLE_FLOATING_SEARCH_BAR", false,
                     "Keep All Apps search bar at the bottom (but above keyboard if open)");
 
-    public static final BooleanFlag ENABLE_QUICK_LAUNCH_V2 = new DeviceFlag(
-            "ENABLE_QUICK_LAUNCH_V2", false, "Use quick launch v2 "
-            + "behavior. Quick search and quick launch v1 would be unavailable if this is enabled");
-
-    public static final BooleanFlag GBOARD_UPDATE_ENTER_KEY = new DeviceFlag(
-            "GBOARD_UPDATE_ENTER_KEY", false, "Update gBoard enter key "
-            + "icon dynamically based on top search content for Quick Launch V2");
-
     public static final BooleanFlag ENABLE_HIDE_HEADER = new DeviceFlag("ENABLE_HIDE_HEADER",
             true, "Hide header on keyboard before typing in all apps");
 
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 6d127b3..981e3a6 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public boolean onActivityReady(Launcher launcher, boolean alreadyOnHome) {
+    public boolean init(Launcher launcher, boolean alreadyOnHome) {
         AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
         launcher.getStateManager().goToState(NORMAL, alreadyOnHome /* animated */);
         launcher.getDragLayer().setOnDragListener(this);
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index fb924c1..af43ae8 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -72,8 +72,8 @@
     }
 
     @Override
-    public boolean onActivityReady(Launcher launcher, boolean alreadyOnHome) {
-        super.onActivityReady(launcher, alreadyOnHome);
+    public boolean init(Launcher launcher, boolean alreadyOnHome) {
+        super.init(launcher, alreadyOnHome);
         if (!alreadyOnHome) {
             launcher.useFadeOutAnimationForLauncherStart(mCancelSignal);
         }
diff --git a/src/com/android/launcher3/util/ActivityTracker.java b/src/com/android/launcher3/util/ActivityTracker.java
index 5f93a66..7af1a13 100644
--- a/src/com/android/launcher3/util/ActivityTracker.java
+++ b/src/com/android/launcher3/util/ActivityTracker.java
@@ -20,6 +20,8 @@
 import com.android.launcher3.BaseActivity;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -28,15 +30,8 @@
  */
 public final class ActivityTracker<T extends BaseActivity> {
 
-    public static final int TYPE_INIT = 0;
-    public static final int TYPE_DESTROY = 1;
-    public static final int TYPE_BOTH = 2;
-
     private WeakReference<T> mCurrentActivity = new WeakReference<>(null);
-    private CopyOnWriteArrayList<SchedulerCallback<T>> mActivityReadyCallbacks =
-            new CopyOnWriteArrayList<>();
-    private CopyOnWriteArrayList<SchedulerCallback<T>> mActivityDestroyedCallbacks =
-            new CopyOnWriteArrayList<>();
+    private CopyOnWriteArrayList<SchedulerCallback<T>> mCallbacks = new CopyOnWriteArrayList<>();
 
     @Nullable
     public <R extends T> R getCreatedActivity() {
@@ -47,74 +42,32 @@
         if (mCurrentActivity.get() == activity) {
             mCurrentActivity.clear();
         }
-        for (SchedulerCallback<T> cb : mActivityDestroyedCallbacks) {
-            cb.onActivityDestroyed();
-            unregisterCallback(cb, TYPE_DESTROY);
-        }
     }
 
-    /** Registers an activity create callback. */
+    /**
+     * Call {@link SchedulerCallback#init(BaseActivity, boolean)} when the
+     * activity is ready. If the activity is already created, this is called immediately.
+     *
+     * The tracker maintains a strong ref to the callback, so it is up to the caller to return
+     * {@code false} in the callback OR to unregister the callback explicitly.
+     *
+     * @param callback The callback to call init() on when the activity is ready.
+     */
     public void registerCallback(SchedulerCallback<T> callback) {
-        registerCallback(callback, TYPE_INIT);
-    }
-
-    /**
-     * Call {@link SchedulerCallback#onActivityReady(BaseActivity, boolean)} when the
-     * activity is ready and/or {@link SchedulerCallback#onActivityDestroyed()} when the activity
-     * is destroyed.
-     *
-     * If type is {@link ActivityTracker#TYPE_INIT} TYPE_INIT or
-     * {@link ActivityTracker#TYPE_BOTH} and the activity is already created, this
-     * {@link SchedulerCallback#onActivityReady(BaseActivity, boolean)} is called immediately.
-     *
-     * If type is {@link ActivityTracker#TYPE_DESTROY} or
-     * {@link ActivityTracker#TYPE_BOTH} and the activity is already destroyed,
-     * {@link SchedulerCallback#onActivityDestroyed()} is called immediately.
-     *
-     * The tracker maintains a strong ref to the callbacks, so it is up to the caller to return
-     * {@code false} in {@link SchedulerCallback#onActivityReady(BaseActivity, boolean)} OR to
-     * unregister the callback explicitly.
-     *
-     * @param callback The callback to call init() or cleanUp() on when the activity is ready or
-     *                 destroyed.
-     * @param type whether to use this callback on activity create, destroy or both.
-     */
-    public void registerCallback(SchedulerCallback<T> callback, int type) {
         T activity = mCurrentActivity.get();
-        if (type == TYPE_INIT || type == TYPE_BOTH) {
-            mActivityReadyCallbacks.add(callback);
-            if (activity != null) {
-                if (!callback.onActivityReady(activity, activity.isStarted())) {
-                    unregisterCallback(callback, TYPE_INIT);
-                }
+        mCallbacks.add(callback);
+        if (activity != null) {
+            if (!callback.init(activity, activity.isStarted())) {
+                unregisterCallback(callback);
             }
         }
-        if (type == TYPE_DESTROY || type == TYPE_BOTH) {
-            mActivityDestroyedCallbacks.add(callback);
-            if (activity == null) {
-                callback.onActivityDestroyed();
-                unregisterCallback(callback, TYPE_DESTROY);
-            }
-        }
-    }
-
-    /**
-     * Unregisters a registered activity create callback.
-     */
-    public void unregisterCallback(SchedulerCallback<T> callback) {
-        unregisterCallback(callback, TYPE_INIT);
     }
 
     /**
      * Unregisters a registered callback.
      */
-    public void unregisterCallback(SchedulerCallback<T> callback, int type) {
-        if (type == TYPE_INIT || type == TYPE_BOTH) {
-            mActivityReadyCallbacks.remove(callback);
-        }
-        if (type == TYPE_DESTROY || type == TYPE_BOTH) {
-            mActivityDestroyedCallbacks.remove(callback);
-        }
+    public void unregisterCallback(SchedulerCallback<T> callback) {
+        mCallbacks.remove(callback);
     }
 
     public boolean handleCreate(T activity) {
@@ -128,8 +81,8 @@
 
     private boolean handleIntent(T activity, boolean alreadyOnHome) {
         boolean handled = false;
-        for (SchedulerCallback<T> cb : mActivityReadyCallbacks) {
-            if (!cb.onActivityReady(activity, alreadyOnHome)) {
+        for (SchedulerCallback<T> cb : mCallbacks) {
+            if (!cb.init(activity, alreadyOnHome)) {
                 // Callback doesn't want any more updates
                 unregisterCallback(cb);
             }
@@ -145,11 +98,6 @@
          * @param alreadyOnHome Whether the activity is already started.
          * @return Whether to continue receiving callbacks (i.e. if the activity is recreated).
          */
-        boolean onActivityReady(T activity, boolean alreadyOnHome);
-
-        /**
-         * Called then the activity gets destroyed.
-         */
-        default void onActivityDestroyed() { }
+        boolean init(T activity, boolean alreadyOnHome);
     }
 }
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 9ca0dd1..8e3daf3 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -131,7 +131,10 @@
      * Returns whether taskbar is transient.
      */
     public static boolean isTransientTaskbar(Context context) {
-        if (FORCE_PERSISTENT_TASKBAR.get()) {
+        // TODO(b/258604917): When running in test harness, use !sTransientTaskbarStatusForTests
+        //  once tests are updated to expect new persistent behavior such as not allowing long press
+        //  to stash.
+        if (!Utilities.IS_RUNNING_IN_TEST_HARNESS && FORCE_PERSISTENT_TASKBAR.get()) {
             return false;
         }
         return getNavigationMode(context) == NavigationMode.NO_BUTTON
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 12e8b54..140440e 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher3.util;
 
-import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-
 import android.app.AppOpsManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -31,7 +29,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
@@ -40,7 +37,6 @@
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 import android.widget.Toast;
 
 import androidx.annotation.NonNull;
@@ -296,25 +292,6 @@
     }
 
     /**
-     * Finds a system apk which had a broadcast receiver listening to a particular action.
-     * @param action intent action used to find the apk
-     * @return a pair of apk package name and the resources.
-     */
-    public static Pair<String, Resources> findSystemApk(String action, PackageManager pm) {
-        final Intent intent = new Intent(action);
-        for (ResolveInfo info : pm.queryBroadcastReceivers(intent, MATCH_SYSTEM_ONLY)) {
-            final String packageName = info.activityInfo.packageName;
-            try {
-                final Resources res = pm.getResourcesForApplication(packageName);
-                return Pair.create(packageName, res);
-            } catch (NameNotFoundException e) {
-                Log.w(TAG, "Failed to find resources for " + packageName);
-            }
-        }
-        return null;
-    }
-
-    /**
      * Returns true if the intent is a valid launch intent for a launcher activity of an app.
      * This is used to identify shortcuts which are different from the ones exposed by the
      * applications' manifest file.
diff --git a/src/com/android/launcher3/util/Partner.java b/src/com/android/launcher3/util/Partner.java
new file mode 100644
index 0000000..220ab56
--- /dev/null
+++ b/src/com/android/launcher3/util/Partner.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014 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.util;
+
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.util.Log;
+import android.util.Pair;
+
+/**
+ * Utilities to discover and interact with partner customizations. There can
+ * only be one set of customizations on a device, and it must be bundled with
+ * the system.
+ */
+public class Partner {
+
+    static final String TAG = "Launcher.Partner";
+
+    /** Marker action used to discover partner */
+    private static final String
+            ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";
+
+    /**
+     * Find and return partner details, or {@code null} if none exists.
+     */
+    public static Partner get(PackageManager pm) {
+        return get(pm, ACTION_PARTNER_CUSTOMIZATION);
+    }
+
+    /**
+     * Find and return partner details, or {@code null} if none exists.
+     */
+    public static Partner get(PackageManager pm, String action) {
+        Pair<String, Resources> apkInfo = findSystemApk(action, pm);
+        return apkInfo != null ? new Partner(apkInfo.first, apkInfo.second) : null;
+    }
+
+    private final String mPackageName;
+    private final Resources mResources;
+
+    private Partner(String packageName, Resources res) {
+        mPackageName = packageName;
+        mResources = res;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public Resources getResources() {
+        return mResources;
+    }
+
+    /**
+     * Returns the xml resource Id for the provided name, or 0 is the resource is not found
+     */
+    public int getXmlResId(String layoutName) {
+        return getResources().getIdentifier(layoutName, "xml", getPackageName());
+    }
+
+    /**
+     * Returns the integer resource value for the provided resource name,
+     * or default value if the resource name is not present
+     */
+    public int getIntValue(String resName, int defaultValue) {
+        int resId = getResources().getIdentifier(resName, "integer", getPackageName());
+        return resId > 0 ? getResources().getInteger(resId) : defaultValue;
+    }
+
+    /**
+     * Returns the dimension value for the provided resource name,
+     * or default value if the resource name is not present
+     */
+    public float getDimenValue(String resName, int defaultValue) {
+        int resId = getResources().getIdentifier(resName, "dimen", getPackageName());
+        return resId > 0 ? getResources().getDimension(resId) : defaultValue;
+    }
+
+    /**
+     * Finds a system apk which had a broadcast receiver listening to a particular action.
+     * @param action intent action used to find the apk
+     * @return a pair of apk package name and the resources.
+     */
+    private static Pair<String, Resources> findSystemApk(String action, PackageManager pm) {
+        final Intent intent = new Intent(action);
+        for (ResolveInfo info : pm.queryBroadcastReceivers(intent, MATCH_SYSTEM_ONLY)) {
+            final String packageName = info.activityInfo.packageName;
+            try {
+                final Resources res = pm.getResourcesForApplication(packageName);
+                return Pair.create(packageName, res);
+            } catch (NameNotFoundException e) {
+                Log.w(TAG, "Failed to find resources for " + packageName);
+            }
+        }
+        return null;
+    }
+}
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index a8753ed..9da7e0f 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -41,6 +41,7 @@
 
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -150,11 +151,13 @@
                 SimpleReorderCase.class.getSimpleName());
     }
 
+    @Ignore
     @Test
     public void pushTest() throws ExecutionException, InterruptedException {
         runTestCaseMap(PushReorderCase.TEST_BY_GRID_SIZE, PushReorderCase.class.getSimpleName());
     }
 
+    @Ignore
     @Test
     public void fullReorder() throws ExecutionException, InterruptedException {
         runTestCaseMap(FullReorderCase.TEST_BY_GRID_SIZE, FullReorderCase.class.getSimpleName());
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 2c9785c..3f4a1c1 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -37,6 +37,7 @@
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -64,6 +65,7 @@
         mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
     }
 
+    @Ignore
     @Test
     @PortraitLandscape
     public void testWidgetConfig() throws Throwable {
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index 93329fa..9d5763b 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -38,6 +38,7 @@
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayDeque;
@@ -110,6 +111,7 @@
         }
     }
 
+    @Ignore
     @Test
     @ScreenRecord // b/260722220
     public void testShortcutIconWithTheme() throws Exception {
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index bddb593..80e4116 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -55,7 +55,7 @@
     }
 
     /** Find the web suggestion from search suggestion's title text */
-    public void findWebSuggest(String text) {
+    public void verifyWebSuggestIsPresent(String text) {
         ArrayList<UiObject2> goldenGateResults =
                 new ArrayList<>(mLauncher.waitForObjectsInContainer(
                         mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),