Merge "Swipe up to home animation changes." into ub-launcher3-qt-dev
diff --git a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
index 62e40d1..fe10a7a 100644
--- a/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
+++ b/go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.quickstep.views.IconRecentsView.REMOTE_APP_TO_OVERVIEW_DURATION;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
@@ -42,6 +43,7 @@
     private final ActivityControlHelper<T> mHelper;
     private final int mTargetTaskId;
     private IconRecentsView mRecentsView;
+    private AppToOverviewAnimationListener mAnimationReadyListener;
 
     AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) {
         mHelper = helper;
@@ -49,12 +51,24 @@
     }
 
     /**
+     * Set listener to various points in the animation preparing to animate.
+     *
+     * @param listener listener
+     */
+    void setAnimationListener(AppToOverviewAnimationListener listener) {
+        mAnimationReadyListener = listener;
+    }
+
+    /**
      * Callback for when the activity is ready/initialized.
      *
      * @param activity the activity that is ready
      * @param wasVisible true if it was visible before
      */
     boolean onActivityReady(T activity, Boolean wasVisible) {
+        if (mAnimationReadyListener != null) {
+            mAnimationReadyListener.onActivityReady(activity);
+        }
         ActivityControlHelper.AnimationFactory factory =
                 mHelper.prepareRecentsUI(activity, wasVisible,
                         false /* animate activity */, (controller) -> {
@@ -79,6 +93,9 @@
      */
     @Override
     public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
+        if (mAnimationReadyListener != null) {
+            mAnimationReadyListener.onWindowAnimationCreated();
+        }
         AnimatorSet anim = new AnimatorSet();
         if (mRecentsView == null) {
             if (Log.isLoggable(TAG, Log.WARN)) {
@@ -118,7 +135,11 @@
             return anim;
         }
 
-        mRecentsView.playRemoteAppToRecentsAnimation(anim, closingAppTarget, recentsTarget);
+        if (closingAppTarget.activityType == ACTIVITY_TYPE_HOME) {
+            mRecentsView.playRemoteHomeToRecentsAnimation(anim, closingAppTarget, recentsTarget);
+        } else {
+            mRecentsView.playRemoteAppToRecentsAnimation(anim, closingAppTarget, recentsTarget);
+        }
 
         return anim;
     }
@@ -131,4 +152,21 @@
     long getRecentsLaunchDuration() {
         return REMOTE_APP_TO_OVERVIEW_DURATION;
     }
+
+    /**
+     * Listener for various points in the app to overview animation preparing to animate.
+     */
+    interface AppToOverviewAnimationListener {
+        /**
+         * Logic for when activity we're animating to is ready
+         *
+         * @param activity activity to animate to
+         */
+        void onActivityReady(BaseDraggingActivity activity);
+
+        /**
+         * Logic for when we've created the app to recents animation.
+         */
+        void onWindowAnimationCreated();
+    }
 }
diff --git a/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
index d39a66c..eb0c5b9 100644
--- a/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
+++ b/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java
@@ -45,12 +45,12 @@
     @Override
     public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible,
             boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
-        // TODO: Logic for setting remote animation
         if (activityVisible) {
             return (transitionLength) -> { };
         }
 
         IconRecentsView rv = activity.getOverviewPanel();
+        rv.setUsingRemoteAnimation(true);
         rv.setAlpha(0);
 
         return new AnimationFactory() {
diff --git a/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 379cc10..0fa3d86 100644
--- a/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -18,7 +18,6 @@
 import static com.android.systemui.shared.system.ActivityManagerWrapper
         .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
-import android.animation.AnimatorSet;
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.os.Build;
@@ -30,10 +29,10 @@
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
+import com.android.quickstep.AppToOverviewAnimationProvider.AppToOverviewAnimationListener;
 import com.android.quickstep.views.IconRecentsView;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.LatencyTrackerCompat;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
 /**
  * Helper class to handle various atomic commands for switching between Overview.
@@ -105,7 +104,6 @@
 
         protected final ActivityControlHelper<T> mHelper;
         private final long mCreateTime;
-        private final AppToOverviewAnimationProvider<T> mAnimationProvider;
 
         private final long mToggleClickedTime = SystemClock.uptimeMillis();
         private boolean mUserEventLogged;
@@ -114,8 +112,6 @@
         public RecentsActivityCommand() {
             mHelper = mOverviewComponentObserver.getActivityControlHelper();
             mCreateTime = SystemClock.elapsedRealtime();
-            mAnimationProvider =
-                    new AppToOverviewAnimationProvider<>(mHelper, RecentsModel.getRunningTaskId());
 
             // Preload the plan
             mRecentsModel.getTasks(null);
@@ -136,11 +132,37 @@
                 return;
             }
 
+            AppToOverviewAnimationProvider<T> provider =
+                    new AppToOverviewAnimationProvider<>(mHelper, RecentsModel.getRunningTaskId());
+            provider.setAnimationListener(
+                    new AppToOverviewAnimationListener() {
+                        @Override
+                        public void onActivityReady(BaseDraggingActivity activity) {
+                            if (!mUserEventLogged) {
+                                activity.getUserEventDispatcher().logActionCommand(
+                                        LauncherLogProto.Action.Command.RECENTS_BUTTON,
+                                        mHelper.getContainerType(),
+                                        LauncherLogProto.ContainerType.TASKSWITCHER);
+                                mUserEventLogged = true;
+                            }
+                        }
+
+                        @Override
+                        public void onWindowAnimationCreated() {
+                            if (LatencyTrackerCompat.isEnabled(mContext)) {
+                                LatencyTrackerCompat.logToggleRecents(
+                                        (int) (SystemClock.uptimeMillis() - mToggleClickedTime));
+                            }
+
+                            mListener.unregister();
+                        }
+                    });
+
             // Otherwise, start overview.
-            mListener = mHelper.createActivityInitListener(this::onActivityReady);
+            mListener = mHelper.createActivityInitListener(provider::onActivityReady);
             mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
-                    this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
-                    mAnimationProvider.getRecentsLaunchDuration());
+                    provider, mContext, mMainThreadExecutor.getHandler(),
+                    provider.getRecentsLaunchDuration());
         }
 
         protected boolean handleCommand(long elapsedTime) {
@@ -155,27 +177,5 @@
             }
             return false;
         }
-
-        private boolean onActivityReady(T activity, Boolean wasVisible) {
-            if (!mUserEventLogged) {
-                activity.getUserEventDispatcher().logActionCommand(
-                        LauncherLogProto.Action.Command.RECENTS_BUTTON,
-                        mHelper.getContainerType(),
-                        LauncherLogProto.ContainerType.TASKSWITCHER);
-                mUserEventLogged = true;
-            }
-            return mAnimationProvider.onActivityReady(activity, wasVisible);
-        }
-
-        private AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
-            if (LatencyTrackerCompat.isEnabled(mContext)) {
-                LatencyTrackerCompat.logToggleRecents(
-                        (int) (SystemClock.uptimeMillis() - mToggleClickedTime));
-            }
-
-            mListener.unregister();
-
-            return mAnimationProvider.createWindowAnimation(targetCompats);
-        }
     }
 }
diff --git a/go/quickstep/src/com/android/quickstep/TaskActionController.java b/go/quickstep/src/com/android/quickstep/TaskActionController.java
index 0e921c0..f49fa3e 100644
--- a/go/quickstep/src/com/android/quickstep/TaskActionController.java
+++ b/go/quickstep/src/com/android/quickstep/TaskActionController.java
@@ -16,14 +16,17 @@
 package com.android.quickstep;
 
 import static com.android.quickstep.TaskAdapter.TASKS_START_POSITION;
+import static com.android.quickstep.TaskUtils.getLaunchComponentKeyForTask;
 
 import android.app.ActivityOptions;
 import android.view.View;
 
 import androidx.annotation.NonNull;
 
+import com.android.launcher3.logging.StatsLogManager;
 import com.android.quickstep.views.TaskItemView;
 import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 /**
@@ -34,10 +37,13 @@
 
     private final TaskListLoader mLoader;
     private final TaskAdapter mAdapter;
+    private final StatsLogManager mStatsLogManager;
 
-    public TaskActionController(TaskListLoader loader, TaskAdapter adapter) {
+    public TaskActionController(TaskListLoader loader, TaskAdapter adapter,
+            StatsLogManager logManager) {
         mLoader = loader;
         mAdapter = adapter;
+        mStatsLogManager = logManager;
     }
 
     /**
@@ -56,10 +62,11 @@
         int width = v.getMeasuredWidth();
         int height = v.getMeasuredHeight();
 
+        TaskKey key = viewHolder.getTask().get().key;
         ActivityOptions opts = ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
-        ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(
-                viewHolder.getTask().get().key, opts, null /* resultCallback */,
-                null /* resultCallbackHandler */);
+        ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(key, opts,
+                null /* resultCallback */, null /* resultCallbackHandler */);
+        mStatsLogManager.logTaskLaunch(null /* view */, getLaunchComponentKeyForTask(key));
     }
 
     /**
@@ -71,6 +78,7 @@
         ActivityOptions opts = ActivityOptions.makeBasic();
         ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
                 null /* resultCallback */, null /* resultCallbackHandler */);
+        mStatsLogManager.logTaskLaunch(null /* view */, getLaunchComponentKeyForTask(task.key));
     }
 
     /**
@@ -87,6 +95,7 @@
         ActivityManagerWrapper.getInstance().removeTask(task.key.id);
         mLoader.removeTask(task);
         mAdapter.notifyItemRemoved(position);
+        // TODO(b/131840601): Add logging point for removal.
     }
 
     /**
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index 8276078..bcb6343 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -153,6 +153,8 @@
     private View mContentView;
     private boolean mTransitionedFromApp;
     private boolean mUsingRemoteAnimation;
+    private boolean mStartedEnterAnimation;
+    private boolean mShowStatusBarForegroundScrim;
     private AnimatorSet mLayoutAnimation;
     private final ArraySet<View> mLayingOutViews = new ArraySet<>();
     private Rect mInsets;
@@ -182,7 +184,8 @@
         mTaskLoader = new TaskListLoader(mContext);
         mTaskAdapter = new TaskAdapter(mTaskLoader);
         mTaskAdapter.setOnClearAllClickListener(view -> animateClearAllTasks());
-        mTaskActionController = new TaskActionController(mTaskLoader, mTaskAdapter);
+        mTaskActionController = new TaskActionController(mTaskLoader, mTaskAdapter,
+                mActivity.getStatsLogManager());
         mTaskAdapter.setActionController(mTaskActionController);
         mTaskLayoutManager = new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */);
         RecentsModel.INSTANCE.get(context).addThumbnailChangeListener(listener);
@@ -232,12 +235,8 @@
                         case ITEM_TYPE_CLEAR_ALL:
                             outRect.top = (int) res.getDimension(
                                     R.dimen.clear_all_item_view_top_margin);
-                            int desiredBottomMargin = (int) res.getDimension(
+                            outRect.bottom = (int) res.getDimension(
                                     R.dimen.clear_all_item_view_bottom_margin);
-                            // Only add bottom margin if insets aren't enough.
-                            if (mInsets.bottom < desiredBottomMargin) {
-                                outRect.bottom = desiredBottomMargin - mInsets.bottom;
-                            }
                             break;
                         case ITEM_TYPE_TASK:
                             int desiredTopMargin = (int) res.getDimension(
@@ -298,6 +297,7 @@
      * becomes visible.
      */
     public void onBeginTransitionToOverview() {
+        mStartedEnterAnimation = false;
         if (mContext.getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
             // Scroll to bottom of task in landscape mode. This is a non-issue in portrait mode as
             // all tasks should be visible to fill up the screen in portrait mode and the view will
@@ -322,16 +322,22 @@
                         + "of items to animate to.");
             }
             // Possible that task list loads faster than adapter changes propagate to layout so
-            // only start content fill animation if there aren't any pending adapter changes.
-            if (!mTaskRecyclerView.hasPendingAdapterUpdates()) {
+            // only start content fill animation if there aren't any pending adapter changes and
+            // we've started the on enter layout animation.
+            boolean needsContentFillAnimation =
+                    !mTaskRecyclerView.hasPendingAdapterUpdates() && mStartedEnterAnimation;
+            if (needsContentFillAnimation) {
                 // Set item animator for content filling animation. The item animator will switch
                 // back to the default on completion
                 mTaskRecyclerView.setItemAnimator(mLoadingContentItemAnimator);
+                mTaskAdapter.notifyItemRangeRemoved(TASKS_START_POSITION + numActualItems,
+                        numEmptyItems - numActualItems);
+                mTaskAdapter.notifyItemRangeChanged(TASKS_START_POSITION, numActualItems,
+                        CHANGE_EVENT_TYPE_EMPTY_TO_CONTENT);
+            } else {
+                // Notify change without animating.
+                mTaskAdapter.notifyDataSetChanged();
             }
-            mTaskAdapter.notifyItemRangeRemoved(TASKS_START_POSITION + numActualItems,
-                    numEmptyItems - numActualItems);
-            mTaskAdapter.notifyItemRangeChanged(TASKS_START_POSITION, numActualItems,
-                    CHANGE_EVENT_TYPE_EMPTY_TO_CONTENT);
         });
     }
 
@@ -401,7 +407,14 @@
      * @param showStatusBarForegroundScrim true to show the scrim, false to hide
      */
     public void setShowStatusBarForegroundScrim(boolean showStatusBarForegroundScrim) {
-        boolean shouldShow = mInsets.top != 0 && showStatusBarForegroundScrim;
+        mShowStatusBarForegroundScrim = showStatusBarForegroundScrim;
+        if (mShowStatusBarForegroundScrim != showStatusBarForegroundScrim) {
+            updateStatusBarScrim();
+        }
+    }
+
+    private void updateStatusBarScrim() {
+        boolean shouldShow = mInsets.top != 0 && mShowStatusBarForegroundScrim;
         mActivity.getDragLayer().setForeground(shouldShow ? mStatusBarForegroundScrim : null);
     }
 
@@ -622,6 +635,54 @@
             }
         });
         mLayoutAnimation.start();
+        mStartedEnterAnimation = true;
+    }
+
+    /**
+     * Play remote app to recents animation when the app is the home activity. We use a simple
+     * cross-fade here. Note this is only used if the home activity is a separate app than the
+     * recents activity.
+     *
+     * @param anim animator set
+     * @param homeTarget the home surface thats closing
+     * @param recentsTarget the surface containing recents
+     */
+    public void playRemoteHomeToRecentsAnimation(@NonNull AnimatorSet anim,
+            @NonNull RemoteAnimationTargetCompat homeTarget,
+            @NonNull RemoteAnimationTargetCompat recentsTarget) {
+        SyncRtSurfaceTransactionApplierCompat surfaceApplier =
+                new SyncRtSurfaceTransactionApplierCompat(this);
+
+        SurfaceParams[] params = new SurfaceParams[2];
+        int boostedMode = MODE_CLOSING;
+
+        ValueAnimator remoteHomeAnim = ValueAnimator.ofFloat(0, 1);
+        remoteHomeAnim.setDuration(REMOTE_APP_TO_OVERVIEW_DURATION);
+
+        remoteHomeAnim.addUpdateListener(valueAnimator -> {
+            float val = (float) valueAnimator.getAnimatedValue();
+            float alpha;
+            RemoteAnimationTargetCompat visibleTarget;
+            RemoteAnimationTargetCompat invisibleTarget;
+            if (val < .5f) {
+                visibleTarget = homeTarget;
+                invisibleTarget = recentsTarget;
+                alpha = 1 - (val * 2);
+            } else {
+                visibleTarget = recentsTarget;
+                invisibleTarget = homeTarget;
+                alpha = (val - .5f) * 2;
+            }
+            params[0] = new SurfaceParams(visibleTarget.leash, alpha, null /* matrix */,
+                    null /* windowCrop */, getLayer(visibleTarget, boostedMode),
+                    0 /* cornerRadius */);
+            params[1] = new SurfaceParams(invisibleTarget.leash, 0.0f, null /* matrix */,
+                    null /* windowCrop */, getLayer(invisibleTarget, boostedMode),
+                    0 /* cornerRadius */);
+            surfaceApplier.scheduleApply(params);
+        });
+        anim.play(remoteHomeAnim);
+        animateFadeInLayoutAnimation();
     }
 
     /**
@@ -641,12 +702,14 @@
             // enough time to take in the data change, bind a new view, and lay out the new view.
             // TODO: Have a fallback to animate to
             anim.play(ValueAnimator.ofInt(0, 1).setDuration(REMOTE_APP_TO_OVERVIEW_DURATION));
+            return;
         }
         final Matrix appMatrix = new Matrix();
         playRemoteTransYAnim(anim, appMatrix);
         playRemoteAppScaleDownAnim(anim, appMatrix, appTarget, recentsTarget,
                 bottomView.getThumbnailView());
         playRemoteTaskListFadeIn(anim, bottomView);
+        mStartedEnterAnimation = true;
     }
 
     /**
@@ -828,6 +891,9 @@
         mInsets = insets;
         mTaskRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
         mTaskRecyclerView.invalidateItemDecorations();
+        if (mInsets.top != 0) {
+            updateStatusBarScrim();
+        }
     }
 
     /**
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
index 0b8c1c5..fa28106 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
@@ -158,10 +158,10 @@
     public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
             String container) {
         // TODO: Use the full shortcut info
-        AppTarget target = new AppTarget.Builder(new AppTargetId("shortcut:" + shortcutId))
-                .setTarget(packageName, user)
-                .setClassName(shortcutId)
-                .build();
+        AppTarget target = new AppTarget
+                .Builder(new AppTargetId("shortcut:" + shortcutId), packageName, user)
+                    .setClassName(shortcutId)
+                    .build();
         sendLaunch(target, container);
     }
 
@@ -169,10 +169,10 @@
     @UiThread
     public void onStartApp(ComponentName cn, UserHandle user, String container) {
         if (cn != null) {
-            AppTarget target = new AppTarget.Builder(new AppTargetId("app:" + cn))
-                    .setTarget(cn.getPackageName(), user)
-                    .setClassName(cn.getClassName())
-                    .build();
+            AppTarget target = new AppTarget
+                    .Builder(new AppTargetId("app:" + cn), cn.getPackageName(), user)
+                        .setClassName(cn.getClassName())
+                        .build();
             sendLaunch(target, container);
         }
     }
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 48a163d..6dad9af 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
@@ -67,8 +67,8 @@
 
     // TODO (b/129421797): Update the client constants
     public enum Client {
-        HOME("GEL"),
-        OVERVIEW("OVERVIEW_GEL");
+        HOME("home"),
+        OVERVIEW("overview");
 
         public final String id;
 
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index ffe3633..47ce44c 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -149,10 +149,10 @@
             List<AppTarget> targets = new ArrayList<>(activities.length);
             for (LauncherActivityInfo info : activities) {
                 ComponentName cn = info.getComponentName();
-                AppTarget target = new AppTarget.Builder(new AppTargetId("app:" + cn))
-                        .setTarget(cn.getPackageName(), info.getUser())
-                        .setClassName(cn.getClassName())
-                        .build();
+                AppTarget target =
+                        new AppTarget.Builder(new AppTargetId("app:" + cn), cn.getPackageName(), info.getUser())
+                            .setClassName(cn.getClassName())
+                            .build();
                 targets.add(target);
             }
             mCallback.onTargetsAvailable(targets);
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index d6f992f..65f9d6b 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -90,7 +90,7 @@
 
     // Usually we show the back button when a floating view is open. Instead, hide for these types.
     public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
-            | TYPE_SNACKBAR;
+            | TYPE_SNACKBAR | TYPE_WIDGET_RESIZE_FRAME | TYPE_LISTENER;
 
     public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_LISTENER;
 
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 4275f31..58fc73d 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
+import android.content.pm.PackageInstaller;
 import android.content.pm.ShortcutInfo;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -56,7 +57,9 @@
     public static LauncherAppsCompat getInstance(Context context) {
         synchronized (sInstanceLock) {
             if (sInstance == null) {
-                if (Utilities.ATLEAST_OREO) {
+                if (Utilities.ATLEAST_Q) {
+                    sInstance = new LauncherAppsCompatVQ(context.getApplicationContext());
+                } else if (Utilities.ATLEAST_OREO) {
                     sInstance = new LauncherAppsCompatVO(context.getApplicationContext());
                 } else {
                     sInstance = new LauncherAppsCompatVL(context.getApplicationContext());
@@ -83,4 +86,6 @@
             UserHandle user);
     public abstract List<ShortcutConfigActivityInfo> getCustomShortcutActivityList(
             @Nullable PackageUserKey packageUser);
+
+    public abstract List<PackageInstaller.SessionInfo> getAllPackageInstallerSessions();
 }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index fc48ba7..1d19b53 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -22,6 +22,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
@@ -199,5 +200,10 @@
         }
         return result;
     }
+
+    @Override
+    public List<PackageInstaller.SessionInfo> getAllPackageInstallerSessions() {
+        return mContext.getPackageManager().getPackageInstaller().getAllSessions();
+    }
 }
 
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVQ.java b/src/com/android/launcher3/compat/LauncherAppsCompatVQ.java
new file mode 100644
index 0000000..0a1811e
--- /dev/null
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVQ.java
@@ -0,0 +1,36 @@
+/*
+ * 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.launcher3.compat;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInstaller;
+
+import java.util.List;
+
+@TargetApi(29)
+public class LauncherAppsCompatVQ extends LauncherAppsCompatVO {
+
+    LauncherAppsCompatVQ(Context context) {
+        super(context);
+    }
+
+    public List<PackageInstaller.SessionInfo> getAllPackageInstallerSessions() {
+        return mLauncherApps.getAllPackageInstallerSessions();
+    }
+}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index fe7b4e5..a34ca50 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -27,6 +27,7 @@
 import android.text.TextUtils;
 import android.util.SparseArray;
 
+import com.android.launcher3.Utilities;
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
@@ -49,6 +50,7 @@
     private final Handler mWorker;
     private final Context mAppContext;
     private final HashMap<String,Boolean> mSessionVerifiedMap = new HashMap<>();
+    private final LauncherAppsCompat mLauncherApps;
 
     PackageInstallerCompatVL(Context context) {
         mAppContext = context.getApplicationContext();
@@ -56,6 +58,7 @@
         mCache = LauncherAppState.getInstance(context).getIconCache();
         mWorker = new Handler(LauncherModel.getWorkerLooper());
         mInstaller.registerSessionCallback(mCallback, mWorker);
+        mLauncherApps = LauncherAppsCompat.getInstance(context);
     }
 
     @Override
@@ -171,7 +174,9 @@
 
     @Override
     public List<SessionInfo> getAllVerifiedSessions() {
-        List<SessionInfo> list = new ArrayList<>(mInstaller.getAllSessions());
+        List<SessionInfo> list = new ArrayList<>(Utilities.ATLEAST_Q
+                ? mLauncherApps.getAllPackageInstallerSessions()
+                : mInstaller.getAllSessions());
         Iterator<SessionInfo> it = list.iterator();
         while (it.hasNext()) {
             if (verify(it.next()) == null) {
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 73f11b2..cd0ae3d 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -568,6 +568,17 @@
             }
         });
 
+        if (originalView instanceof BubbleTextView) {
+            BubbleTextView btv = (BubbleTextView) originalView;
+            btv.forceHideDot(true);
+            fade.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    btv.forceHideDot(false);
+                }
+            });
+        }
+
         if (originalView instanceof FolderIcon) {
             FolderIcon folderIcon = (FolderIcon) originalView;
             folderIcon.setBackgroundVisible(false);
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 60d2850..8f5e7fe 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -17,16 +17,12 @@
 package com.android.launcher3.tapl;
 
 import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
-import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
-import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
 
 import android.graphics.Point;
 import android.os.SystemClock;
 import android.view.MotionEvent;
 
 import androidx.annotation.NonNull;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.Until;
 
 import com.android.launcher3.TestProtocol;
 
@@ -59,8 +55,6 @@
                 "want to switch from background to overview")) {
             verifyActiveContainer();
             goToOverviewUnchecked(BACKGROUND_APP_STATE_ORDINAL);
-            mLauncher.assertTrue("Overview not visible", mLauncher.getDevice().wait(
-                    Until.hasObject(By.pkg(getOverviewPackageName())), WAIT_TIME_MS));
             return new BaseOverview(mLauncher);
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 70d8cf7..b3a369a 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -33,6 +33,7 @@
 
     BaseOverview(LauncherInstrumentation launcher) {
         super(launcher);
+        verifyActiveContainer();
     }
 
     @Override
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 4d8ff1b..a63d468 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -18,6 +18,7 @@
 
 import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
 import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
 
 import android.app.ActivityManager;
 import android.app.Instrumentation;
@@ -176,17 +177,19 @@
             // Workaround, use constructed context because both the instrumentation context and the
             // app context are not constructed with resources that take overlays into account
             final Context ctx = baseContext.createPackageContext("android", 0);
-            log("Interaction mode = " + getCurrentInteractionMode(ctx));
-            if (isGesturalMode(ctx)) {
-                return NavigationModel.ZERO_BUTTON;
-            } else if (isSwipeUpMode(ctx)) {
-                return NavigationModel.TWO_BUTTON;
-            } else if (isLegacyMode(ctx)) {
-                return NavigationModel.THREE_BUTTON;
-            } else {
-                fail("Can't detect navigation mode");
+            for (int i = 0; i < 100; ++i) {
+                log("Interaction mode = " + getCurrentInteractionMode(ctx));
+                if (isGesturalMode(ctx)) {
+                    return NavigationModel.ZERO_BUTTON;
+                } else if (isSwipeUpMode(ctx)) {
+                    return NavigationModel.TWO_BUTTON;
+                } else if (isLegacyMode(ctx)) {
+                    return NavigationModel.THREE_BUTTON;
+                }
+                Thread.sleep(100);
             }
-        } catch (PackageManager.NameNotFoundException e) {
+            fail("Can't detect navigation mode");
+        } catch (Exception e) {
             fail(e.toString());
         }
         return NavigationModel.THREE_BUTTON;
@@ -294,14 +297,14 @@
                     } else {
                         waitUntilGone(APPS_RES_ID);
                     }
-                    // Fall through
-                }
-                case BASE_OVERVIEW: {
                     waitUntilGone(WORKSPACE_RES_ID);
                     waitUntilGone(WIDGETS_RES_ID);
 
                     return waitForLauncherObject(OVERVIEW_RES_ID);
                 }
+                case BASE_OVERVIEW: {
+                    return waitForFallbackLauncherObject(OVERVIEW_RES_ID);
+                }
                 case BACKGROUND: {
                     waitUntilGone(WORKSPACE_RES_ID);
                     waitUntilGone(APPS_RES_ID);
@@ -526,10 +529,22 @@
         return object;
     }
 
+    @NonNull
+    UiObject2 waitForFallbackLauncherObject(String resName) {
+        final BySelector selector = getFallbackLauncherObjectSelector(resName);
+        final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
+        assertNotNull("Can't find a fallback launcher object; selector: " + selector, object);
+        return object;
+    }
+
     BySelector getLauncherObjectSelector(String resName) {
         return By.res(getLauncherPackageName(), resName);
     }
 
+    BySelector getFallbackLauncherObjectSelector(String resName) {
+        return By.res(getOverviewPackageName(), resName);
+    }
+
     String getLauncherPackageName() {
         return mDevice.getLauncherPackageName();
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index e8a0b54..c0bafa2 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -58,9 +58,13 @@
             verifyActiveContainer();
             final UiObject2 hotseat = mHotseat;
             final Point start = hotseat.getVisibleCenter();
+            start.y = hotseat.getVisibleBounds().bottom - 1;
             final int swipeHeight = mLauncher.getTestInfo(
                     TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT).
                     getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+            LauncherInstrumentation.log(
+                    "switchToAllApps: swipeHeight = " + swipeHeight + ", slop = "
+                            + mLauncher.getTouchSlop());
             mLauncher.swipe(
                     start.x,
                     start.y,