diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 750f673625..e1456b17ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -25,6 +25,7 @@ import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; import static com.android.quickstep.views.SplitPlaceholderView.ALPHA_FLOAT; +import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL; import android.annotation.TargetApi; import android.os.Build; @@ -73,7 +74,7 @@ public final class RecentsViewStateController extends if (toState.overviewUi) { // While animating into recents, update the visible task data as needed - builder.addOnFrameCallback(mRecentsView::loadVisibleTaskData); + builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL)); mRecentsView.updateEmptyMessage(); } else { builder.addListener( diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 54f6ce6dc6..82bfa9b9a9 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -29,6 +29,7 @@ import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; +import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.PropertySetter; @@ -70,7 +71,7 @@ public class FallbackRecentsStateController implements StateHandler mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL)); mRecentsView.updateEmptyMessage(); setProperties(toState, config, setter); diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index f216985a94..4d8176c7e5 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -315,6 +315,10 @@ public abstract class RecentsView extends PagedView private final ClearAllButton mClearAllButton; private final Rect mClearAllButtonDeadZoneRect = new Rect(); private final Rect mTaskViewDeadZoneRect = new Rect(); + /** + * Reflects if Recents is currently in the middle of a gesture + */ + private boolean mGestureActive; private final ScrollState mScrollState = new ScrollState(); // Keeps track of the previously known visible tasks for purposes of loading/unloading task data @@ -624,8 +628,8 @@ public abstract class RecentsView extends PagedView return; } mModel.getIconCache().clear(); - unloadVisibleTaskData(); - loadVisibleTaskData(); + unloadVisibleTaskData(TaskView.FLAG_UPDATE_ICON); + loadVisibleTaskData(TaskView.FLAG_UPDATE_ICON); } public void init(OverviewActionsView actionsView, SplitPlaceholderView splitPlaceholderView) { @@ -908,7 +912,7 @@ public abstract class RecentsView extends PagedView } // Unload existing visible task data - unloadVisibleTaskData(); + unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL); TaskView ignoreResetTaskView = mIgnoreResetTaskId == -1 ? null : getTaskView(mIgnoreResetTaskId); @@ -1031,7 +1035,7 @@ public abstract class RecentsView extends PagedView updateCurveProperties(); // Update the set of visible task's data - loadVisibleTaskData(); + loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL); setTaskModalness(0); } @@ -1147,7 +1151,7 @@ public abstract class RecentsView extends PagedView } // After scrolling, update the visible task's data - loadVisibleTaskData(); + loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL); } // Update the high res thumbnail loader state @@ -1210,7 +1214,7 @@ public abstract class RecentsView extends PagedView * Iterates through all the tasks, and loads the associated task data for newly visible tasks, * and unloads the associated task data for tasks that are no longer visible. */ - public void loadVisibleTaskData() { + public void loadVisibleTaskData(@TaskView.TaskDataChanges int dataChanges) { if (!mOverviewStateEnabled || mTaskListChangeId == -1) { // Skip loading visible task data if we've already left the overview state, or if the // task list hasn't been loaded yet (the task views will not reflect the task list) @@ -1252,12 +1256,18 @@ public abstract class RecentsView extends PagedView continue; } if (!mHasVisibleTaskData.get(task.key.id)) { - taskView.onTaskListVisibilityChanged(true /* visible */); + // Ignore thumbnail update if it's current running task during the gesture + // We snapshot at end of gesture, it will update then + int changes = dataChanges; + if (taskView == getRunningTaskView() && mGestureActive) { + changes &= ~TaskView.FLAG_UPDATE_THUMBNAIL; + } + taskView.onTaskListVisibilityChanged(true /* visible */, changes); } mHasVisibleTaskData.put(task.key.id, visible); } else { if (mHasVisibleTaskData.get(task.key.id)) { - taskView.onTaskListVisibilityChanged(false /* visible */); + taskView.onTaskListVisibilityChanged(false /* visible */, dataChanges); } mHasVisibleTaskData.delete(task.key.id); } @@ -1267,12 +1277,12 @@ public abstract class RecentsView extends PagedView /** * Unloads any associated data from the currently visible tasks */ - private void unloadVisibleTaskData() { + private void unloadVisibleTaskData(@TaskView.TaskDataChanges int dataChanges) { for (int i = 0; i < mHasVisibleTaskData.size(); i++) { if (mHasVisibleTaskData.valueAt(i)) { TaskView taskView = getTaskView(mHasVisibleTaskData.keyAt(i)); if (taskView != null) { - taskView.onTaskListVisibilityChanged(false /* visible */); + taskView.onTaskListVisibilityChanged(false /* visible */, dataChanges); } } } @@ -1310,7 +1320,7 @@ public abstract class RecentsView extends PagedView mRecentsAnimationController = null; mLiveTileParams.setTargetSet(null); - unloadVisibleTaskData(); + unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL); setCurrentPage(0); mDwbToastShown = false; mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0); @@ -1358,6 +1368,7 @@ public abstract class RecentsView extends PagedView * Called when a gesture from an app is starting. */ public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) { + mGestureActive = true; // This needs to be called before the other states are set since it can create the task view if (mOrientationState.setGestureActive(true)) { updateOrientationHandler(); @@ -1428,6 +1439,7 @@ public abstract class RecentsView extends PagedView * Called when a gesture from an app has finished, and the animation to the target has ended. */ public void onGestureAnimationEnd() { + mGestureActive = false; if (mOrientationState.setGestureActive(false)) { updateOrientationHandler(); } @@ -2733,7 +2745,7 @@ public abstract class RecentsView extends PagedView @Override protected void notifyPageSwitchListener(int prevPage) { super.notifyPageSwitchListener(prevPage); - loadVisibleTaskData(); + loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL); updateEnabledOverlays(); } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 2b7e6fd059..a2acab880f 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -42,6 +42,8 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -67,6 +69,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.Toast; +import androidx.annotation.IntDef; import androidx.annotation.NonNull; import com.android.launcher3.DeviceProfile; @@ -106,6 +109,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.QuickStepContract; +import java.lang.annotation.Retention; import java.util.Collections; import java.util.List; import java.util.function.Consumer; @@ -117,6 +121,19 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private static final String TAG = TaskView.class.getSimpleName(); + public static final int FLAG_UPDATE_ICON = 1; + public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1; + + public static final int FLAG_UPDATE_ALL = FLAG_UPDATE_ICON | FLAG_UPDATE_THUMBNAIL; + + /** + * Used in conjunction with {@link #onTaskListVisibilityChanged(boolean, int)}, providing more + * granularity on which components of this task require an update + */ + @Retention(SOURCE) + @IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL}) + public @interface TaskDataChanges {} + /** * The alpha of a black scrim on a page in the carousel as it leaves the screen. * In the resting position of the carousel, the adjacent pages have about half this scrim. @@ -557,7 +574,19 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } } + /** + * See {@link TaskDataChanges} + * @param visible If this task view will be visible to the user in overview or hidden + */ public void onTaskListVisibilityChanged(boolean visible) { + onTaskListVisibilityChanged(visible, FLAG_UPDATE_ALL); + } + + /** + * See {@link TaskDataChanges} + * @param visible If this task view will be visible to the user in overview or hidden + */ + public void onTaskListVisibilityChanged(boolean visible, @TaskDataChanges int changes) { if (mTask == null) { return; } @@ -568,22 +597,37 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { RecentsModel model = RecentsModel.INSTANCE.get(getContext()); TaskThumbnailCache thumbnailCache = model.getThumbnailCache(); TaskIconCache iconCache = model.getIconCache(); - mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground( - mTask, thumbnail -> mSnapshotView.setThumbnail(mTask, thumbnail)); - mIconLoadRequest = iconCache.updateIconInBackground(mTask, - (task) -> { - setIcon(task.icon); - mDigitalWellBeingToast.initialize(mTask); - }); + + if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) { + mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground( + mTask, thumbnail -> { + mSnapshotView.setThumbnail(mTask, thumbnail); + }); + } + if (needsUpdate(changes, FLAG_UPDATE_ICON)) { + mIconLoadRequest = iconCache.updateIconInBackground(mTask, + (task) -> { + setIcon(task.icon); + mDigitalWellBeingToast.initialize(mTask); + }); + } } else { - mSnapshotView.setThumbnail(null, null); - setIcon(null); - // Reset the task thumbnail reference as well (it will be fetched from the cache or - // reloaded next time we need it) - mTask.thumbnail = null; + if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) { + mSnapshotView.setThumbnail(null, null); + // Reset the task thumbnail reference as well (it will be fetched from the cache or + // reloaded next time we need it) + mTask.thumbnail = null; + } + if (needsUpdate(changes, FLAG_UPDATE_ICON)) { + setIcon(null); + } } } + private boolean needsUpdate(@TaskDataChanges int dataChange, @TaskDataChanges int flag) { + return (dataChange & flag) == flag; + } + private void cancelPendingLoadTasks() { if (mThumbnailLoadRequest != null) { mThumbnailLoadRequest.cancel();