Merge "Not deleting assistant from sources" into ub-launcher3-master
diff --git a/go/quickstep/src/com/android/quickstep/TaskActionController.java b/go/quickstep/src/com/android/quickstep/TaskActionController.java
index 77b287b..71bee91 100644
--- a/go/quickstep/src/com/android/quickstep/TaskActionController.java
+++ b/go/quickstep/src/com/android/quickstep/TaskActionController.java
@@ -42,6 +42,9 @@
      * @param viewHolder the task view holder to launch
      */
     public void launchTask(TaskHolder viewHolder) {
+        if (viewHolder.getTask() == null) {
+            return;
+        }
         TaskItemView itemView = (TaskItemView) (viewHolder.itemView);
         View v = itemView.getThumbnailView();
         int left = 0;
@@ -60,6 +63,9 @@
      * @param viewHolder the task view holder to remove
      */
     public void removeTask(TaskHolder viewHolder) {
+        if (viewHolder.getTask() == null) {
+            return;
+        }
         int position = viewHolder.getAdapterPosition();
         Task task = viewHolder.getTask();
         ActivityManagerWrapper.getInstance().removeTask(task.key.id);
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
index c98eca6..674fcae 100644
--- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -28,6 +28,7 @@
 import com.android.systemui.shared.recents.model.Task;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
@@ -40,6 +41,7 @@
     private final TaskListLoader mLoader;
     private final ArrayMap<Integer, TaskItemView> mTaskIdToViewMap = new ArrayMap<>();
     private TaskActionController mTaskActionController;
+    private boolean mIsShowingLoadingUi;
 
     public TaskAdapter(@NonNull TaskListLoader loader) {
         mLoader = loader;
@@ -50,6 +52,18 @@
     }
 
     /**
+     * Sets all positions in the task adapter to loading views, binding new views if necessary.
+     * This changes the task adapter's view of the data, so the appropriate notify events should be
+     * called in addition to this method to reflect the changes.
+     *
+     * @param isShowingLoadingUi true to bind loading task views to all positions, false to return
+     *                           to the real data
+     */
+    public void setIsShowingLoadingUi(boolean isShowingLoadingUi) {
+        mIsShowingLoadingUi = isShowingLoadingUi;
+    }
+
+    /**
      * Get task item view for a given task id if it's attached to the view.
      *
      * @param taskId task id to search for
@@ -70,6 +84,10 @@
 
     @Override
     public void onBindViewHolder(TaskHolder holder, int position) {
+        if (mIsShowingLoadingUi) {
+            holder.bindEmptyUi();
+            return;
+        }
         List<Task> tasks = mLoader.getCurrentTaskList();
         if (position >= tasks.size()) {
             // Task list has updated.
@@ -79,13 +97,13 @@
         holder.bindTask(task);
         mLoader.loadTaskIconAndLabel(task, () -> {
             // Ensure holder still has the same task.
-            if (task.equals(holder.getTask())) {
+            if (Objects.equals(task, holder.getTask())) {
                 holder.getTaskItemView().setIcon(task.icon);
                 holder.getTaskItemView().setLabel(task.titleDescription);
             }
         });
         mLoader.loadTaskThumbnail(task, () -> {
-            if (task.equals(holder.getTask())) {
+            if (Objects.equals(task, holder.getTask())) {
                 holder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail);
             }
         });
@@ -93,16 +111,27 @@
 
     @Override
     public void onViewAttachedToWindow(@NonNull TaskHolder holder) {
+        if (holder.getTask() == null) {
+            return;
+        }
         mTaskIdToViewMap.put(holder.getTask().key.id, (TaskItemView) holder.itemView);
     }
 
     @Override
     public void onViewDetachedFromWindow(@NonNull TaskHolder holder) {
+        if (holder.getTask() == null) {
+            return;
+        }
         mTaskIdToViewMap.remove(holder.getTask().key.id);
     }
 
     @Override
     public int getItemCount() {
-        return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY);
+        if (mIsShowingLoadingUi) {
+            // Show loading version of all items.
+            return MAX_TASKS_TO_DISPLAY;
+        } else {
+            return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY);
+        }
     }
 }
diff --git a/go/quickstep/src/com/android/quickstep/TaskHolder.java b/go/quickstep/src/com/android/quickstep/TaskHolder.java
index 744afd7..98dc989 100644
--- a/go/quickstep/src/com/android/quickstep/TaskHolder.java
+++ b/go/quickstep/src/com/android/quickstep/TaskHolder.java
@@ -15,7 +15,7 @@
  */
 package com.android.quickstep;
 
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import com.android.quickstep.views.TaskItemView;
@@ -50,11 +50,23 @@
     }
 
     /**
-     * Gets the task currently bound to this view
+     * Bind a generic empty UI to the holder to make it clear that the item is loading/unbound and
+     * should not be expected to react to user input.
+     */
+    public void bindEmptyUi() {
+        mTask = null;
+        // TODO: Set the task view to a loading, empty UI.
+        // Temporarily using the one below for visual confirmation but should be swapped out to new
+        // UI later.
+        mTaskItemView.resetTaskItemView();
+    }
+
+    /**
+     * Gets the task currently bound to this view. May be null if task holder is in a loading state.
      *
      * @return the current task
      */
-    public @NonNull Task getTask() {
+    public @Nullable Task getTask() {
         return mTask;
     }
 }
diff --git a/go/quickstep/src/com/android/quickstep/TaskListLoader.java b/go/quickstep/src/com/android/quickstep/TaskListLoader.java
index 1234989..51b73f1 100644
--- a/go/quickstep/src/com/android/quickstep/TaskListLoader.java
+++ b/go/quickstep/src/com/android/quickstep/TaskListLoader.java
@@ -68,16 +68,26 @@
     }
 
     /**
+     * Whether or not the loader needs to load data to be up to date. This can return true if the
+     * task list is already up to date OR there is already a load in progress for the task list to
+     * become up to date.
+     *
+     * @return true if already up to date or load in progress, false otherwise
+     */
+    public boolean needsToLoad() {
+        return !mRecentsModel.isTaskListValid(mTaskListChangeId);
+    }
+
+    /**
      * Fetches the most recent tasks and updates the task list asynchronously. This call does not
      * provide guarantees the task content (icon, thumbnail, label) are loaded but will fill in
      * what it has. May run the callback immediately if there have been no changes in the task
-     * list.
+     * list since the start of the last load.
      *
      * @param onLoadedCallback callback to run when task list is loaded
      */
     public void loadTaskList(@Nullable Consumer<ArrayList<Task>> onLoadedCallback) {
-        if (mRecentsModel.isTaskListValid(mTaskListChangeId)) {
-            // Current task list is already up to date. No need to update.
+        if (!needsToLoad()) {
             if (onLoadedCallback != null) {
                 onLoadedCallback.accept(mTaskList);
             }
diff --git a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
index c579c8a..734425e 100644
--- a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -49,7 +49,6 @@
             ISystemUiProxy iSystemUiProxy = ISystemUiProxy.Stub
                     .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
             mRecentsModel.setSystemUiProxy(iSystemUiProxy);
-            mRecentsModel.onInitializeSystemUI(bundle);
         }
 
         @Override
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index 5bb4c5a..c06b6ec 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -28,6 +28,10 @@
 import android.util.FloatProperty;
 import android.view.View;
 import android.view.ViewDebug;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.LayoutAnimationController;
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
@@ -69,6 +73,8 @@
                 }
             };
     private static final long CROSSFADE_DURATION = 300;
+    private static final long LAYOUT_ITEM_ANIMATE_IN_DURATION = 150;
+    private static final long LAYOUT_ITEM_ANIMATE_IN_DELAY_BETWEEN = 40;
     private static final long ITEM_ANIMATE_OUT_DURATION = 150;
     private static final long ITEM_ANIMATE_OUT_DELAY_BETWEEN = 40;
     private static final float ITEM_ANIMATE_OUT_TRANSLATION_X_RATIO = .25f;
@@ -84,6 +90,7 @@
     private final TaskListLoader mTaskLoader;
     private final TaskAdapter mTaskAdapter;
     private final TaskActionController mTaskActionController;
+    private final LayoutAnimationController mLayoutAnimation;
 
     private RecentsToActivityHelper mActivityHelper;
     private RecyclerView mTaskRecyclerView;
@@ -99,6 +106,7 @@
         mTaskAdapter = new TaskAdapter(mTaskLoader);
         mTaskActionController = new TaskActionController(mTaskLoader, mTaskAdapter);
         mTaskAdapter.setActionController(mTaskActionController);
+        mLayoutAnimation = createLayoutAnimation();
     }
 
     @Override
@@ -112,6 +120,7 @@
             ItemTouchHelper helper = new ItemTouchHelper(
                     new TaskSwipeCallback(mTaskActionController));
             helper.attachToRecyclerView(mTaskRecyclerView);
+            mTaskRecyclerView.setLayoutAnimation(mLayoutAnimation);
 
             mEmptyView = findViewById(R.id.recent_task_empty_view);
             mContentView = findViewById(R.id.recent_task_content_view);
@@ -131,7 +140,6 @@
         }
     }
 
-
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
@@ -157,10 +165,17 @@
      * becomes visible.
      */
     public void onBeginTransitionToOverview() {
+        mTaskRecyclerView.scheduleLayoutAnimation();
+
         // Load any task changes
+        if (!mTaskLoader.needsToLoad()) {
+            return;
+        }
+        mTaskAdapter.setIsShowingLoadingUi(true);
+        mTaskAdapter.notifyDataSetChanged();
         mTaskLoader.loadTaskList(tasks -> {
-            // TODO: Put up some loading UI while task content is loading. May have to do something
-            // smarter when animating from app to overview.
+            mTaskAdapter.setIsShowingLoadingUi(false);
+            // TODO: Animate the loading UI out and the loaded data in.
             mTaskAdapter.notifyDataSetChanged();
         });
     }
@@ -322,4 +337,18 @@
                     }
                 });
     }
+
+    private static LayoutAnimationController createLayoutAnimation() {
+        AnimationSet anim = new AnimationSet(false /* shareInterpolator */);
+
+        Animation alphaAnim = new AlphaAnimation(0, 1);
+        alphaAnim.setDuration(LAYOUT_ITEM_ANIMATE_IN_DURATION);
+        anim.addAnimation(alphaAnim);
+
+        LayoutAnimationController layoutAnim = new LayoutAnimationController(anim);
+        layoutAnim.setDelay(
+                (float) LAYOUT_ITEM_ANIMATE_IN_DELAY_BETWEEN / LAYOUT_ITEM_ANIMATE_IN_DURATION);
+
+        return layoutAnim;
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 87ae091..79f0c36 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -101,7 +101,6 @@
             MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
             runWhenUserUnlocked(() -> {
                 mRecentsModel.setSystemUiProxy(mISystemUiProxy);
-                mRecentsModel.onInitializeSystemUI(bundle);
                 mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
             });
         }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index d2cd83f..8ab2eb1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -16,6 +16,8 @@
 package com.android.quickstep.util;
 
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
+import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
@@ -97,9 +99,8 @@
             (t, a1) -> a1;
 
     public ClipAnimationHelper(Context context) {
-        mWindowCornerRadius = RecentsModel.INSTANCE.get(context).getWindowCornerRadius();
-        mSupportsRoundedCornersOnWindows = RecentsModel.INSTANCE.get(context)
-                .supportsRoundedCornersOnWindows();
+        mWindowCornerRadius = getWindowCornerRadius(context.getResources());
+        mSupportsRoundedCornersOnWindows = supportsRoundedCornersOnWindows(context.getResources());
         int taskCornerRadiusRes = mSupportsRoundedCornersOnWindows ?
                 R.dimen.task_corner_radius : R.dimen.task_corner_radius_small;
         mTaskCornerRadius = context.getResources().getDimension(taskCornerRadiusRes);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index a9f6311..10533ac 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -46,11 +46,11 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.util.Themes;
-import com.android.quickstep.RecentsModel;
 import com.android.quickstep.TaskOverlayFactory;
 import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.QuickStepContract;
 
 /**
  * A task in the Recents view.
@@ -116,7 +116,7 @@
         mDimmingPaintAfterClearing.setColor(Color.BLACK);
         mActivity = BaseActivity.fromContext(context);
         mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
-        mWindowCornerRadius = RecentsModel.INSTANCE.get(context).getWindowCornerRadius();
+        mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources());
     }
 
     public void bind(Task task) {
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index f77bd65..cda9d4f 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -31,6 +31,7 @@
 import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
+import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
 
@@ -63,12 +64,12 @@
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.launcher3.views.FloatingIconView;
-import com.android.quickstep.RecentsModel;
 import com.android.quickstep.util.MultiValueUpdateListener;
 import com.android.quickstep.util.RemoteAnimationProvider;
 import com.android.quickstep.util.RemoteAnimationTargetSet;
 import com.android.systemui.shared.system.ActivityCompat;
 import com.android.systemui.shared.system.ActivityOptionsCompat;
+import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
 import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat;
 import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
@@ -473,6 +474,10 @@
         });
 
         float shapeRevealDuration = APP_LAUNCH_DURATION * SHAPE_PROGRESS_DURATION;
+
+        final float windowRadius = mDeviceProfile.isMultiWindowMode
+                ? 0 :  getWindowCornerRadius(mLauncher.getResources());
+
         appAnimator.addUpdateListener(new MultiValueUpdateListener() {
             FloatProp mDx = new FloatProp(0, dX, 0, xDuration, AGGRESSIVE_EASE);
             FloatProp mDy = new FloatProp(0, dY, 0, yDuration, AGGRESSIVE_EASE);
@@ -514,13 +519,6 @@
                 float transX0 = temp.left - offsetX;
                 float transY0 = temp.top - offsetY;
 
-                float windowRadius = 0;
-                if (!mDeviceProfile.isMultiWindowMode &&
-                        RecentsModel.INSTANCE.get(mLauncher).supportsRoundedCornersOnWindows()) {
-                    windowRadius = RecentsModel.INSTANCE.get(mLauncher)
-                            .getWindowCornerRadius();
-                }
-
                 SurfaceParams[] params = new SurfaceParams[targets.length];
                 for (int i = targets.length - 1; i >= 0; i--) {
                     RemoteAnimationTargetCompat target = targets[i];
@@ -651,7 +649,7 @@
         ValueAnimator unlockAnimator = ValueAnimator.ofFloat(0, 1);
         unlockAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
         float cornerRadius = mDeviceProfile.isMultiWindowMode ? 0 :
-                RecentsModel.INSTANCE.get(mLauncher).getWindowCornerRadius();
+                QuickStepContract.getWindowCornerRadius(mLauncher.getResources());
         unlockAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
@@ -677,8 +675,8 @@
         Matrix matrix = new Matrix();
         ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
         int duration = CLOSING_TRANSITION_DURATION_MS;
-        float windowCornerRadius = mDeviceProfile.isMultiWindowMode ? 0 :
-                RecentsModel.INSTANCE.get(mLauncher).getWindowCornerRadius();
+        float windowCornerRadius = mDeviceProfile.isMultiWindowMode
+                ? 0 : getWindowCornerRadius(mLauncher.getResources());
         closingAnimator.setDuration(duration);
         closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
             FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7);
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index a65bc33..675cfe2 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -35,6 +35,7 @@
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 
 import java.util.ArrayList;
@@ -62,9 +63,6 @@
     private final TaskIconCache mIconCache;
     private final TaskThumbnailCache mThumbnailCache;
 
-    private float mWindowCornerRadius = 0;
-    private boolean mSupportsRoundedCornersOnWindows;
-
     private RecentsModel(Context context) {
         mContext = context;
         HandlerThread loaderThread = new HandlerThread("TaskThumbnailIconCache",
@@ -76,12 +74,6 @@
         ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
     }
 
-    public void onInitializeSystemUI(Bundle params) {
-        mWindowCornerRadius = params.getFloat(KEY_EXTRA_WINDOW_CORNER_RADIUS, 0);
-        mSupportsRoundedCornersOnWindows =
-                params.getBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, false);
-    }
-
     public TaskIconCache getIconCache() {
         return mIconCache;
     }
@@ -182,14 +174,6 @@
         return mSystemUiProxy;
     }
 
-    public float getWindowCornerRadius() {
-        return mWindowCornerRadius;
-    }
-
-    public boolean supportsRoundedCornersOnWindows() {
-        return mSupportsRoundedCornersOnWindows;
-    }
-
     public void onTrimMemory(int level) {
         if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
             mThumbnailCache.getHighResLoadingState().setVisible(false);
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 895485d..6034791 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -32,7 +32,6 @@
 
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.tapl.TestHelpers;
-import com.android.systemui.shared.system.QuickStepContract;
 
 import org.junit.Assert;
 import org.junit.rules.TestRule;
@@ -78,9 +77,9 @@
                 @Override
                 public void evaluate() throws Throwable {
                     final Context context = getInstrumentation().getContext();
-                    final String prevOverlayPkg = QuickStepContract.isGesturalMode(context)
+                    final String prevOverlayPkg = LauncherInstrumentation.isGesturalMode(context)
                             ? NAV_BAR_MODE_GESTURAL_OVERLAY
-                            : QuickStepContract.isSwipeUpMode(context)
+                            : LauncherInstrumentation.isSwipeUpMode(context)
                                     ? NAV_BAR_MODE_2BUTTON_OVERLAY
                                     : NAV_BAR_MODE_3BUTTON_OVERLAY;
                     final LauncherInstrumentation.NavigationModel originalMode =
@@ -150,4 +149,4 @@
             return base;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7822e05..7804133 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -37,8 +37,6 @@
     <dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
 
     <!-- Hotseat/all-apps scrim -->
-    <dimen name="all_apps_scrim_radius">8dp</dimen>
-    <dimen name="all_apps_scrim_margin">8dp</dimen>
     <dimen name="all_apps_scrim_blur">4dp</dimen>
     <dimen name="vertical_drag_handle_size">24dp</dimen>
     <dimen name="vertical_drag_handle_overlap_workspace">0dp</dimen>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 252cae1..ec63e35 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -44,7 +44,7 @@
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
         <item name="folderDotColor">?android:attr/colorPrimary</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
-        <item name="loadingIconColor">#FFF</item>
+        <item name="loadingIconColor">#CCFFFFFF</item>
 
         <item name="android:windowTranslucentStatus">false</item>
         <item name="android:windowTranslucentNavigation">false</item>
@@ -82,7 +82,7 @@
         <item name="folderDotColor">#FF464646</item>
         <item name="folderIconBorderColor">#FF80868B</item>
         <item name="isMainColorDark">true</item>
-        <item name="loadingIconColor">#000</item>
+        <item name="loadingIconColor">#99FFFFFF</item>
     </style>
 
     <style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark">
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index 639c173..5424a8f 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -33,12 +33,20 @@
 
     class CheckForLongPress implements Runnable {
         public void run() {
+            if (com.android.launcher3.TestProtocol.sDebugTracing) {
+                android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+                        "CheckForLongPress1");
+            }
             if ((mView.getParent() != null) && mView.hasWindowFocus()
                     && !mHasPerformedLongPress) {
                 boolean handled;
                 if (mListener != null) {
                     handled = mListener.onLongClick(mView);
                 } else {
+                    if (com.android.launcher3.TestProtocol.sDebugTracing) {
+                        android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+                                "CheckForLongPress2");
+                    }
                     handled = mView.performLongClick();
                 }
                 if (handled) {
@@ -73,11 +81,20 @@
         }
         mView.postDelayed(mPendingCheckForLongPress,
                 (long) (ViewConfiguration.getLongPressTimeout() * mLongPressTimeoutFactor));
+        if (com.android.launcher3.TestProtocol.sDebugTracing) {
+            android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+                    "postCheckForLongPress: " + ViewConfiguration.getLongPressTimeout() + " "
+                            + mLongPressTimeoutFactor);
+        }
     }
 
     public void cancelLongPress() {
         mHasPerformedLongPress = false;
         if (mPendingCheckForLongPress != null) {
+            if (com.android.launcher3.TestProtocol.sDebugTracing) {
+                android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+                        "cancelLongPress");
+            }
             mView.removeCallbacks(mPendingCheckForLongPress);
             mPendingCheckForLongPress = null;
         }
diff --git a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
index 5f2fb59..23745cb 100644
--- a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.graphics;
 
+import static androidx.core.graphics.ColorUtils.compositeColors;
+
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -47,7 +49,8 @@
         super(b, iconColor);
 
         mProgressPath = progressPath;
-        mPaint.setColor(Themes.getAttrColor(context, R.attr.loadingIconColor));
+        mPaint.setColor(compositeColors(
+                Themes.getAttrColor(context, R.attr.loadingIconColor), iconColor));
     }
 
     @Override
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 0d499c1..a229207 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -82,7 +82,8 @@
     public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         mInflater = LayoutInflater.from(context);
-        mOutlineRadius = getResources().getDimension(R.dimen.bg_round_rect_radius);
+        mOutlineRadius = Themes.getDialogCornerRadius(context,
+                getResources().getDimension(R.dimen.bg_round_rect_radius));
         mLauncher = Launcher.getLauncher(context);
         mIsRtl = Utilities.isRtl(getResources());
 
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 675e2f4..17b7e8d 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -25,11 +25,24 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 
+import com.android.launcher3.R;
+
 /**
  * Various utility methods associated with theming.
  */
 public class Themes {
 
+    public static float getDialogCornerRadius(Context context, float defaultValue) {
+        return getDimension(context, android.R.attr.dialogCornerRadius, defaultValue);
+    }
+
+    public static float getDimension(Context context, int attr, float defaultValue) {
+        TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+        float value = ta.getDimension(0, defaultValue);
+        ta.recycle();
+        return value;
+    }
+
     public static int getColorAccent(Context context) {
         return getAttrColor(context, android.R.attr.colorAccent);
     }
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 46b463b..089d672 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -97,5 +97,13 @@
                 <category android:name="android.intent.category.LAUNCHER_APP" />
             </intent-filter>
         </activity>
+        <activity
+            android:name="com.android.launcher3.testcomponent.BaseTestingActivity"
+            android:label="LauncherTestApp">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
index 904590c..9c6d102 100644
--- a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
+++ b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.util.TypedValue;
 import android.view.View;
@@ -63,6 +64,7 @@
         mView = new LinearLayout(this);
         mView.setPadding(mMargin, mMargin, mMargin, mMargin);
         mView.setOrientation(LinearLayout.VERTICAL);
+        mView.setBackgroundColor(Color.BLUE);
         setContentView(mView);
 
         registerReceiver(mCommandReceiver, new IntentFilter(mAction + SUFFIX_COMMAND));
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index c2e6749..e11e62e 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -330,9 +330,7 @@
     public void testDragAppIcon() throws Throwable {
         try {
             TestProtocol.sDebugTracing = true;
-            LauncherActivityInfo settingsApp = getSettingsApp();
-
-            final String appName = settingsApp.getLabel().toString();
+            final String appName = "LauncherTestApp";
             // 1. Open all apps and wait for load complete.
             // 2. Drag icon to homescreen.
             // 3. Verify that the icon works on homescreen.
@@ -341,7 +339,7 @@
                     getAppIcon(appName).
                     dragToWorkspace().
                     getWorkspaceAppIcon(appName).
-                    launch(settingsApp.getComponentName().getPackageName());
+                    launch(getInstrumentation().getContext().getPackageName());
         } finally {
             TestProtocol.sDebugTracing = false;
         }
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 7a2b7af..16ddba8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -28,7 +28,6 @@
  * Ancestor for AppIcon and AppMenuItem.
  */
 class Launchable {
-    private static final int DRAG_SPEED = 500;
     protected final LauncherInstrumentation mLauncher;
 
     protected final UiObject2 mObject;
@@ -77,8 +76,7 @@
         Workspace.dragIconToWorkspace(
                 mLauncher,
                 this,
-                new Point(device.getDisplayWidth() / 2, device.getDisplayHeight() / 2),
-                DRAG_SPEED);
+                new Point(device.getDisplayWidth() / 2, device.getDisplayHeight() / 2));
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "dragged launchable to workspace")) {
             return new Workspace(mLauncher);
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index c72f7d0..3a45e93 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -16,12 +16,16 @@
 
 package com.android.launcher3.tapl;
 
+import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+
 import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.net.Uri;
 import android.os.Build;
@@ -172,11 +176,11 @@
             // 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);
-            if (QuickStepContract.isGesturalMode(ctx)) {
+            if (isGesturalMode(ctx)) {
                 return NavigationModel.ZERO_BUTTON;
-            } else if (QuickStepContract.isSwipeUpMode(ctx)) {
+            } else if (isSwipeUpMode(ctx)) {
                 return NavigationModel.TWO_BUTTON;
-            } else if (QuickStepContract.isLegacyMode(ctx)) {
+            } else if (isLegacyMode(ctx)) {
                 return NavigationModel.THREE_BUTTON;
             } else {
                 fail("Can't detect navigation mode");
@@ -343,18 +347,33 @@
                 log(action = "0-button: already in workspace");
             } else if (hasLauncherObject(OVERVIEW_RES_ID)) {
                 log(action = "0-button: from overview");
-                mDevice.pressHome();
+                final UiObject2 navBar = waitForSystemUiObject("navigation_bar_frame");
+
+                swipe(
+                        navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+                        navBar.getVisibleBounds().centerX(), 0,
+                        NORMAL_STATE_ORDINAL, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
             } else if (hasLauncherObject(WIDGETS_RES_ID)) {
                 log(action = "0-button: from widgets");
                 mDevice.pressHome();
             } else if (hasLauncherObject(APPS_RES_ID)) {
                 log(action = "0-button: from all apps");
-                mDevice.pressHome();
+                final UiObject2 navBar = waitForSystemUiObject("navigation_bar_frame");
+
+                swipe(
+                        navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+                        navBar.getVisibleBounds().centerX(), 0,
+                        NORMAL_STATE_ORDINAL, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
             } else {
                 log(action = "0-button: from another app");
                 assertTrue("Launcher is visible, don't know how to go home",
                         !mDevice.hasObject(By.pkg(getLauncherPackageName())));
-                mDevice.pressHome();
+                final UiObject2 navBar = waitForSystemUiObject("navigation_bar_frame");
+
+                swipe(
+                        navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+                        navBar.getVisibleBounds().centerX(), 0,
+                        BACKGROUND_APP_STATE_ORDINAL, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
             }
         } else {
             log(action = "clicking home button");
@@ -607,6 +626,46 @@
         }
     }
 
+    public static boolean isGesturalMode(Context context) {
+        return QuickStepContract.isGesturalMode(getCurrentInteractionMode(context));
+    }
+
+    public static boolean isSwipeUpMode(Context context) {
+        return QuickStepContract.isSwipeUpMode(getCurrentInteractionMode(context));
+    }
+
+    public static boolean isLegacyMode(Context context) {
+        return QuickStepContract.isLegacyMode(getCurrentInteractionMode(context));
+    }
+
+    private static int getCurrentInteractionMode(Context context) {
+        return getSystemIntegerRes(context, "config_navBarInteractionMode");
+    }
+
+    private static int getSystemIntegerRes(Context context, String resName) {
+        Resources res = context.getResources();
+        int resId = res.getIdentifier(resName, "integer", "android");
+
+        if (resId != 0) {
+            return res.getInteger(resId);
+        } else {
+            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+            return -1;
+        }
+    }
+
+    private static int getSystemDimensionResId(Context context, String resName) {
+        Resources res = context.getResources();
+        int resId = res.getIdentifier(resName, "dimen", "android");
+
+        if (resId != 0) {
+            return resId;
+        } else {
+            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+            return -1;
+        }
+    }
+
     static void sleep(int duration) {
         try {
             Thread.sleep(duration);
@@ -616,8 +675,10 @@
 
     int getEdgeSensitivityWidth() {
         try {
-            return QuickStepContract.getEdgeSensitivityWidth(
-                    mInstrumentation.getTargetContext().createPackageContext("android", 0)) + 1;
+            final Context context = mInstrumentation.getTargetContext().createPackageContext(
+                    "android", 0);
+            return context.getResources().getDimensionPixelSize(
+                    getSystemDimensionResId(context, "config_backGestureInset")) + 1;
         } catch (PackageManager.NameNotFoundException e) {
             fail("Can't get edge sensitivity: " + e);
             return 0;
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index f04afa0..943332e 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -21,7 +21,9 @@
 import static junit.framework.TestCase.assertTrue;
 
 import android.graphics.Point;
+import android.os.SystemClock;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -35,8 +37,8 @@
  */
 public final class Workspace extends Home {
     private static final float FLING_SPEED = 3500.0F;
+    private static final int DRAG_DURACTION = 2000;
     private final UiObject2 mHotseat;
-    private final int ICON_DRAG_SPEED = LauncherInstrumentation.needSlowGestures() ? 100 : 570;
 
     Workspace(LauncherInstrumentation launcher) {
         super(launcher);
@@ -116,8 +118,7 @@
                     mLauncher,
                     getHotseatAppIcon("Chrome"),
                     new Point(mLauncher.getDevice().getDisplayWidth(),
-                            workspace.getVisibleBounds().centerY()),
-                    (int) (ICON_DRAG_SPEED * mLauncher.getDisplayDensity()));
+                            workspace.getVisibleBounds().centerY()));
             verifyActiveContainer();
         }
         assertTrue("Home screen workspace didn't become scrollable",
@@ -134,10 +135,16 @@
                 mHotseat, AppIcon.getAppIconSelector(appName, mLauncher)));
     }
 
-    static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
-            Point dest, int icon_drag_speed) {
+    static void dragIconToWorkspace(
+            LauncherInstrumentation launcher, Launchable launchable, Point dest) {
         LauncherInstrumentation.log("dragIconToWorkspace: begin");
-        launchable.getObject().drag(dest, icon_drag_speed);
+        final Point launchableCenter = launchable.getObject().getVisibleCenter();
+        final long downTime = SystemClock.uptimeMillis();
+        launcher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, launchableCenter);
+        launcher.waitForLauncherObject("deep_shortcuts_container");
+        launcher.movePointer(downTime, DRAG_DURACTION, launchableCenter, dest);
+        launcher.sendPointer(
+                downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest);
         LauncherInstrumentation.log("dragIconToWorkspace: end");
         launcher.waitUntilGone("drop_target_bar");
     }