Unloading thumbnails from task views once recents is hidden

- Re-enabling the high res thumbnail loader, ensuring that we clean up
  the visible recent tasks when the associated views are removed
- When the recents state is re-entered, we will trigger the loading of
  the data anew (which will usually just fetch data from the existing
  cache if launcher was not stopped)

Bug: 74537246
Change-Id: I9cd69015461e1de34b4b65faeb9adb8aebd1dd3d
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 2a2e9c5..132a0c5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -152,5 +152,9 @@
 
     private void applyProgress() {
         mRecentsView.setAlpha(mTransitionProgress.value * mVisibilityMultiplier.value);
+        if (mIsRecentsSlidingInOrOut) {
+            // While animating into recents, update the visible task data as needed
+            mRecentsView.loadVisibleTaskData();
+        }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index b4ce646..392b73f 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -210,13 +210,13 @@
 
     public void onStart() {
         mRecentsTaskLoader.startLoader(mContext);
-//        mRecentsTaskLoader.getHighResThumbnailLoader().setVisible(true);
+        mRecentsTaskLoader.getHighResThumbnailLoader().setVisible(true);
     }
 
     public void onTrimMemory(int level) {
         if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
             // We already stop the loader in UI_HIDDEN, so stop the high res loader as well
-//            mRecentsTaskLoader.getHighResThumbnailLoader().setVisible(false);
+            mRecentsTaskLoader.getHighResThumbnailLoader().setVisible(false);
         }
         mRecentsTaskLoader.onTrimMemory(level);
     }
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index 3cd1179..52d95e5 100644
--- a/quickstep/src/com/android/quickstep/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -111,7 +111,9 @@
     private boolean mScrimOnLeft;
 
     private boolean mFirstTaskIconScaledDown = false;
-    private SparseBooleanArray mPrevVisibleTasks = new SparseBooleanArray();
+
+    // Keeps track of the previously known visible tasks for purposes of loading/unloading task data
+    private SparseBooleanArray mHasVisibleTaskData = new SparseBooleanArray();
 
     public RecentsView(Context context) {
         this(context, null);
@@ -217,6 +219,20 @@
     }
 
     @Override
+    public void onViewRemoved(View child) {
+        super.onViewRemoved(child);
+
+        // Clear the task data for the removed child if it was visible
+        Task task = ((TaskView) child).getTask();
+        if (mHasVisibleTaskData.get(task.key.id)) {
+            mHasVisibleTaskData.delete(task.key.id);
+            RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
+            loader.unloadTaskData(task);
+            loader.getHighResThumbnailLoader().onTaskInvisible(task);
+        }
+    }
+
+    @Override
     public void setInsets(Rect insets) {
         mInsets.set(insets);
         DeviceProfile dp = Launcher.getLauncher(getContext()).getDeviceProfile();
@@ -295,7 +311,6 @@
     }
 
     private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) {
-        final RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
         TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null;
         if (stack == null) {
             removeAllViews();
@@ -317,13 +332,13 @@
         }
         while (getChildCount() > requiredChildCount) {
             final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1);
-            final Task task = taskView.getTask();
             removeView(taskView);
-            loader.unloadTaskData(task);
-//            loader.getHighResThumbnailLoader().onTaskInvisible(task);
         }
         setLayoutTransition(mLayoutTransition);
 
+        // Unload existing visible task data
+        unloadVisibleTaskData();
+
         // Rebind and reset all task views
         for (int i = requiredChildCount - 1; i >= 0; i--) {
             final int pageIndex = requiredChildCount - i - 1;
@@ -333,8 +348,8 @@
             taskView.resetVisualProperties();
         }
         updateCurveProperties();
-        // Reload the set of visible task's data
-        mPrevVisibleTasks.clear();
+
+        // Update the set of visible task's data
         loadVisibleTaskData();
         applyIconScale(false /* animate */);
 
@@ -421,7 +436,7 @@
 
         // Update the high res thumbnail loader
         RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
-//        loader.getHighResThumbnailLoader().setFlingingFast(isFlingingFast);
+        loader.getHighResThumbnailLoader().setFlingingFast(isFlingingFast);
         return scrolling;
     }
 
@@ -453,30 +468,50 @@
      * Iterates through all thet asks, and loads the associated task data for newly visible tasks,
      * and unloads the associated task data for tasks that are no longer visible.
      */
-    private void loadVisibleTaskData() {
+    public void loadVisibleTaskData() {
         RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
         int centerPageIndex = getPageNearestToCenterOfScreen();
         int lower = Math.max(0, centerPageIndex - 2);
         int upper = Math.min(centerPageIndex + 2, getChildCount() - 1);
-        for (int i = 0; i < getChildCount(); i++) {
+        int numChildren = getChildCount();
+
+        // Update the task data for the in/visible children
+        for (int i = 0; i < numChildren; i++) {
             TaskView taskView = (TaskView) getChildAt(i);
             Task task = taskView.getTask();
             boolean visible = lower <= i && i <= upper;
             if (visible) {
-                if (!mPrevVisibleTasks.get(i)) {
+                if (!mHasVisibleTaskData.get(task.key.id)) {
                     loader.loadTaskData(task);
-//                    loader.getHighResThumbnailLoader().onTaskVisible(task);
+                    loader.getHighResThumbnailLoader().onTaskVisible(task);
                 }
+                mHasVisibleTaskData.put(task.key.id, visible);
             } else {
-                if (mPrevVisibleTasks.get(i)) {
+                if (mHasVisibleTaskData.get(task.key.id)) {
                     loader.unloadTaskData(task);
-//                    loader.getHighResThumbnailLoader().onTaskInvisible(task);
+                    loader.getHighResThumbnailLoader().onTaskInvisible(task);
                 }
+                mHasVisibleTaskData.delete(task.key.id);
             }
-            mPrevVisibleTasks.put(i, visible);
         }
     }
 
+    /**
+     * Unloads any associated data from the currently visible tasks
+     */
+    private void unloadVisibleTaskData() {
+        RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
+        for (int i = 0; i < mHasVisibleTaskData.size(); i++) {
+            if (mHasVisibleTaskData.valueAt(i)) {
+                TaskView taskView = getTaskView(mHasVisibleTaskData.keyAt(i));
+                Task task = taskView.getTask();
+                loader.unloadTaskData(task);
+                loader.getHighResThumbnailLoader().onTaskInvisible(task);
+            }
+        }
+        mHasVisibleTaskData.clear();
+    }
+
     public void onTaskDismissed(TaskView taskView) {
         ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
         removeView(taskView);
@@ -486,14 +521,11 @@
     }
 
     public void reset() {
+        unloadVisibleTaskData();
         mRunningTaskId = -1;
         setCurrentPage(0);
     }
 
-    public int getRunningTaskId() {
-        return mRunningTaskId;
-    }
-
     /**
      * Reloads the view if anything in recents changed.
      */
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index d39ec3e..eb73879 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -756,11 +756,13 @@
 
     @Override
     public void onViewAdded(View child) {
+        super.onViewAdded(child);
         dispatchPageCountChanged();
     }
 
     @Override
     public void onViewRemoved(View child) {
+        super.onViewRemoved(child);
         mCurrentPage = validateNewPage(mCurrentPage);
         dispatchPageCountChanged();
     }