Prevent hotseat updates if it is visible to the user.

Test: manual

Fixes: 168653219

Changing app icons under the user's finger could be disruptive. Added a checks for whether the hotseatand all apps predictions are visible and callbacks to update them when they become hidden.

Change-Id: Ib9e6e904e9f662ecfaeea6a2fe21d1d81ba39b96
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 5b066c6..e7880fd 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -108,6 +108,8 @@
 
     AllAppsSectionDecorator.SectionDecorationHandler mDecorationHandler;
 
+    @Nullable private List<ItemInfo> mPendingPredictedItems;
+
     public PredictionRowView(@NonNull Context context) {
         this(context, null);
     }
@@ -203,6 +205,16 @@
      * we can optimize by swapping them in place.
      */
     public void setPredictedApps(List<ItemInfo> items) {
+        if (isShown() && getWindowVisibility() == View.VISIBLE) {
+            mPendingPredictedItems = items;
+            return;
+        }
+
+        applyPredictedApps(items);
+    }
+
+    private void applyPredictedApps(List<ItemInfo> items) {
+        mPendingPredictedItems = null;
         mPredictedApps.clear();
         items.stream()
                 .filter(itemInfo -> itemInfo instanceof WorkspaceItemInfo)
@@ -341,4 +353,13 @@
     public View getFocusedChild() {
         return getChildAt(0);
     }
+
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+
+        if (mPendingPredictedItems != null && !isVisible) {
+            applyPredictedApps(mPendingPredictedItems);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 3807350..76bab59 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -251,6 +251,26 @@
      * Sets or updates the predicted items
      */
     public void setPredictedItems(FixedContainerItems items) {
+        if (mHotseat.isShown() && mHotseat.getWindowVisibility() == View.VISIBLE) {
+            mHotseat.setOnVisibilityAggregatedCallback((isVisible) -> {
+                if (isVisible) {
+                    return;
+                }
+                mHotseat.setOnVisibilityAggregatedCallback(null);
+
+                applyPredictedItems(items);
+            });
+        } else {
+            mHotseat.setOnVisibilityAggregatedCallback(null);
+
+            applyPredictedItems(items);
+        }
+    }
+
+    /**
+     * Sets or updates the predicted items only once the hotseat becomes hidden to the user
+     */
+    private void applyPredictedItems(FixedContainerItems items) {
         mPredictedItems = items.items;
         if (mPredictedItems.isEmpty()) {
             HotseatRestoreHelper.restoreBackup(mLauncher);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 6547b53..e4bdb39 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -25,6 +25,10 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.Nullable;
+
+import java.util.function.Consumer;
+
 /**
  * View class that represents the bottom row of the home screen.
  */
@@ -34,6 +38,7 @@
     private boolean mHasVerticalHotseat;
     private Workspace mWorkspace;
     private boolean mSendTouchToWorkspace;
+    @Nullable private Consumer<Boolean> mOnVisibilityAggregatedCallback;
 
     public Hotseat(Context context) {
         this(context, null);
@@ -129,4 +134,18 @@
         }
         return event.getY() > getCellHeight();
     }
+
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+
+        if (mOnVisibilityAggregatedCallback != null) {
+            mOnVisibilityAggregatedCallback.accept(isVisible);
+        }
+    }
+
+    /** Sets a callback to be called onVisibilityAggregated */
+    public void setOnVisibilityAggregatedCallback(@Nullable Consumer<Boolean> callback) {
+        mOnVisibilityAggregatedCallback = callback;
+    }
 }