From c06bc41ee003a7e4b5a44ec51bccde36a9f3e82c Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 30 May 2024 12:28:07 +0100 Subject: [PATCH] Use snapshotView references in TaskContainer when possible - Moved majority of TaskContainer.thumbnailViewDeprecated usage to TaskContainer.snapshotView, so they'll cover the new TaskThumbnailView as well - There are afew location left that will be handled as a follow-up - Removed TaskThumbnailView's splitTranslation and use translation directly as it's the only translation we use Bug: 336612373 Test: Ensure all Task CUJs still work without refacorting Test: Ensure major Task CUJs work with refactoring Flag: EXEMPT refactor Flag: com.android.launcher3.enable_refactor_task_thumbnail Change-Id: Ieb52236bc503ce0d0a511249978c1821a82d406e --- .../taskbar/TaskbarUIController.java | 4 +- .../TaskViewTouchController.java | 2 +- .../android/quickstep/TaskOverlayFactory.java | 44 +++++----- .../quickstep/TaskShortcutFactory.java | 27 +++--- .../com/android/quickstep/TaskViewUtils.java | 7 +- .../util/SplitAnimationController.kt | 85 +++++++++---------- .../quickstep/views/DesktopTaskView.kt | 6 +- .../views/DigitalWellBeingToast.java | 4 +- .../quickstep/views/GroupedTaskView.kt | 28 ++---- .../android/quickstep/views/TaskMenuView.java | 27 +++--- .../views/TaskThumbnailViewDeprecated.java | 57 ------------- .../com/android/quickstep/views/TaskView.kt | 39 ++++++--- .../util/SplitAnimationControllerTest.kt | 8 +- 13 files changed, 136 insertions(+), 202 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index ce281c30e4..f24bc214f0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -269,8 +269,8 @@ public class TaskbarUIController { foundTaskView, foundTask, taskContainer.getIconView().getDrawable(), - taskContainer.getThumbnailViewDeprecated(), - taskContainer.getThumbnailViewDeprecated().getThumbnail(), + taskContainer.getSnapshotView(), + taskContainer.getThumbnail(), null /* intent */, null /* user */, info); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index 4bc3c1661e..3c7f335325 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -252,7 +252,7 @@ public abstract class TaskViewTouchController translations = orientationHandler .getDwbLayoutTranslations(mTaskView.getMeasuredWidth(), mTaskView.getMeasuredHeight(), mSplitBounds, deviceProfile, - mTaskView.getThumbnailViews(), mTask.key.id, mBanner); + mTaskView.getSnapshotViews(), mTask.key.id, mBanner); mSplitOffsetTranslationX = translations.first; mSplitOffsetTranslationY = translations.second; updateTranslationY(); diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt index 3e4a953b56..b070244304 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt @@ -68,36 +68,20 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu val initSplitTaskId = getThisTaskCurrentlyInSplitSelection() if (initSplitTaskId == INVALID_TASK_ID) { pagedOrientationHandler.measureGroupedTaskViewThumbnailBounds( - taskContainers[0].thumbnailViewDeprecated, - taskContainers[1].thumbnailViewDeprecated, + taskContainers[0].snapshotView, + taskContainers[1].snapshotView, widthSize, heightSize, splitBoundsConfig, container.deviceProfile, layoutDirection == LAYOUT_DIRECTION_RTL ) - // Should we be having a separate translation step apart from the measuring above? - // The following only applies to large screen for now, but for future reference - // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary - // translation directions - taskContainers[0] - .thumbnailViewDeprecated - .applySplitSelectTranslateX(taskContainers[0].thumbnailViewDeprecated.translationX) - taskContainers[0] - .thumbnailViewDeprecated - .applySplitSelectTranslateY(taskContainers[0].thumbnailViewDeprecated.translationY) - taskContainers[1] - .thumbnailViewDeprecated - .applySplitSelectTranslateX(taskContainers[1].thumbnailViewDeprecated.translationX) - taskContainers[1] - .thumbnailViewDeprecated - .applySplitSelectTranslateY(taskContainers[1].thumbnailViewDeprecated.translationY) } else { // Currently being split with this taskView, let the non-split selected thumbnail // take up full thumbnail area taskContainers .firstOrNull { it.task.key.id != initSplitTaskId } - ?.thumbnailViewDeprecated + ?.snapshotView ?.measure( widthMeasureSpec, MeasureSpec.makeMeasureSpec( @@ -212,8 +196,8 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu taskContainers[0].iconView.asView(), taskContainers[1].iconView.asView(), taskIconHeight, - taskContainers[0].thumbnailViewDeprecated.measuredWidth, - taskContainers[0].thumbnailViewDeprecated.measuredHeight, + taskContainers[0].snapshotView.measuredWidth, + taskContainers[0].snapshotView.measuredHeight, measuredHeight, measuredWidth, isRtl, @@ -308,7 +292,7 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu // Check which of the two apps was selected if ( taskContainers[1].iconView.asView().containsPoint(lastTouchDownPosition) || - taskContainers[1].thumbnailViewDeprecated.containsPoint(lastTouchDownPosition) + taskContainers[1].snapshotView.containsPoint(lastTouchDownPosition) ) { return 1 } diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java index 4f446b203c..8d5ba7766f 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java @@ -238,12 +238,12 @@ public class TaskMenuView extends AbstractFloatingView { mContainer.getDragLayer().getDescendantRectRelativeToSelf( enableOverviewIconMenu() ? getIconView().findViewById(R.id.icon_view_menu_anchor) - : taskContainer.getThumbnailViewDeprecated(), + : taskContainer.getSnapshotView(), sTempRect); Rect insets = mContainer.getDragLayer().getInsets(); BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams(); params.width = orientationHandler.getTaskMenuWidth( - taskContainer.getThumbnailViewDeprecated(), deviceProfile, + taskContainer.getSnapshotView(), deviceProfile, taskContainer.getStagePosition()); // Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start params.gravity = Gravity.LEFT; @@ -277,10 +277,10 @@ public class TaskMenuView extends AbstractFloatingView { // Margin that insets the menuView inside the taskView float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin); setTranslationX(orientationHandler.getTaskMenuX(thumbnailAlignedX, - mTaskContainer.getThumbnailViewDeprecated(), deviceProfile, taskInsetMargin, + mTaskContainer.getSnapshotView(), deviceProfile, taskInsetMargin, getIconView())); setTranslationY(orientationHandler.getTaskMenuY( - thumbnailAlignedY, mTaskContainer.getThumbnailViewDeprecated(), + thumbnailAlignedY, mTaskContainer.getSnapshotView(), mTaskContainer.getStagePosition(), this, taskInsetMargin, getIconView())); } @@ -316,7 +316,7 @@ public class TaskMenuView extends AbstractFloatingView { .createRevealAnimator(this, closing, revealAnimationStartProgress); mRevealAnimator.setInterpolator(enableOverviewIconMenu() ? Interpolators.EMPHASIZED : Interpolators.DECELERATE); - + AnimatorSet.Builder openCloseAnimatorBuilder = mOpenCloseAnimator.play(mRevealAnimator); if (enableOverviewIconMenu()) { IconAppChipView iconAppChip = (IconAppChipView) mTaskContainer.getIconView().asView(); @@ -334,11 +334,13 @@ public class TaskMenuView extends AbstractFloatingView { closing ? mMenuTranslationYBeforeOpen : mMenuTranslationYBeforeOpen + additionalTranslationY); translationYAnim.setInterpolator(EMPHASIZED); + openCloseAnimatorBuilder.with(translationYAnim); ObjectAnimator menuTranslationYAnim = ObjectAnimator.ofFloat( iconAppChip.getMenuTranslationY(), MULTI_PROPERTY_VALUE, closing ? 0 : additionalTranslationY); menuTranslationYAnim.setInterpolator(EMPHASIZED); + openCloseAnimatorBuilder.with(menuTranslationYAnim); float additionalTranslationX = 0; if (mContainer.getDeviceProfile().isLandscape @@ -354,20 +356,15 @@ public class TaskMenuView extends AbstractFloatingView { closing ? mMenuTranslationXBeforeOpen : mMenuTranslationXBeforeOpen - additionalTranslationX); translationXAnim.setInterpolator(EMPHASIZED); + openCloseAnimatorBuilder.with(translationXAnim); ObjectAnimator menuTranslationXAnim = ObjectAnimator.ofFloat( iconAppChip.getMenuTranslationX(), MULTI_PROPERTY_VALUE, closing ? 0 : -additionalTranslationX); menuTranslationXAnim.setInterpolator(EMPHASIZED); - - mOpenCloseAnimator.playTogether(translationYAnim, translationXAnim, - menuTranslationXAnim, menuTranslationYAnim); + openCloseAnimatorBuilder.with(menuTranslationXAnim); } - mOpenCloseAnimator.playTogether(mRevealAnimator, - ObjectAnimator.ofFloat( - mTaskContainer.getThumbnailViewDeprecated(), DIM_ALPHA, - closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA), - ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1)); + openCloseAnimatorBuilder.with(ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1)); if (enableRefactorTaskThumbnail()) { mRevealAnimator.addUpdateListener(animation -> { float animatedFraction = animation.getAnimatedFraction(); @@ -375,6 +372,10 @@ public class TaskMenuView extends AbstractFloatingView { mTaskContainer.getTaskContainerData() .getTaskMenuOpenProgress().setValue(openProgress); }); + } else { + openCloseAnimatorBuilder.with(ObjectAnimator.ofFloat( + mTaskContainer.getThumbnailViewDeprecated(), DIM_ALPHA, + closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA)); } mOpenCloseAnimator.addListener(new AnimationSuccessListener() { @Override diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java index 4283d0e4cf..2afb6a6d52 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java @@ -99,36 +99,6 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab } }; - /** Use to animate thumbnail translationX while first app in split selection is initiated */ - public static final Property SPLIT_SELECT_TRANSLATE_X = - new FloatProperty("splitSelectTranslateX") { - @Override - public void setValue(TaskThumbnailViewDeprecated thumbnail, - float splitSelectTranslateX) { - thumbnail.applySplitSelectTranslateX(splitSelectTranslateX); - } - - @Override - public Float get(TaskThumbnailViewDeprecated thumbnailView) { - return thumbnailView.mSplitSelectTranslateX; - } - }; - - /** Use to animate thumbnail translationY while first app in split selection is initiated */ - public static final Property SPLIT_SELECT_TRANSLATE_Y = - new FloatProperty("splitSelectTranslateY") { - @Override - public void setValue(TaskThumbnailViewDeprecated thumbnail, - float splitSelectTranslateY) { - thumbnail.applySplitSelectTranslateY(splitSelectTranslateY); - } - - @Override - public Float get(TaskThumbnailViewDeprecated thumbnailView) { - return thumbnailView.mSplitSelectTranslateY; - } - }; - private final RecentsViewContainer mContainer; private TaskOverlay mOverlay; private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -160,8 +130,6 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab private boolean mOverlayEnabled; /** Used as a placeholder when the original thumbnail animates out to. */ private boolean mShowSplashForSplitSelection; - private float mSplitSelectTranslateX; - private float mSplitSelectTranslateY; public TaskThumbnailViewDeprecated(Context context) { this(context, null); @@ -415,31 +383,6 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab } } - /** See {@link #SPLIT_SELECT_TRANSLATE_X} */ - protected void applySplitSelectTranslateX(float splitSelectTranslateX) { - mSplitSelectTranslateX = splitSelectTranslateX; - applyTranslateX(); - } - - /** See {@link #SPLIT_SELECT_TRANSLATE_Y} */ - protected void applySplitSelectTranslateY(float splitSelectTranslateY) { - mSplitSelectTranslateY = splitSelectTranslateY; - applyTranslateY(); - } - - private void applyTranslateX() { - setTranslationX(mSplitSelectTranslateX); - } - - private void applyTranslateY() { - setTranslationY(mSplitSelectTranslateY); - } - - protected void resetViewTransforms() { - mSplitSelectTranslateX = 0; - mSplitSelectTranslateY = 0; - } - public TaskView getTaskView() { return (TaskView) getParent(); } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index 7a3b00f197..d4b0040733 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -23,7 +23,9 @@ import android.annotation.IdRes import android.app.ActivityOptions import android.content.Context import android.content.Intent +import android.graphics.Bitmap import android.graphics.Canvas +import android.graphics.Insets import android.graphics.PointF import android.graphics.Rect import android.graphics.drawable.Drawable @@ -138,8 +140,8 @@ constructor( /** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */ get() = taskContainers.map { it.task.key.id }.toIntArray() - val thumbnailViews: Array - get() = taskContainers.map { it.thumbnailViewDeprecated }.toTypedArray() + val snapshotViews: Array + get() = taskContainers.map { it.snapshotView }.toTypedArray() val isGridTask: Boolean /** Returns whether the task is part of overview grid and not being focused. */ @@ -170,6 +172,11 @@ constructor( /** Returns the first thumbnailView of the TaskView. */ get() = taskContainers[0].thumbnailViewDeprecated + @get:Deprecated("Use [taskContainers] instead.") + val firstSnapshotView: View + /** Returns the first snapshotView of the TaskView. */ + get() = taskContainers[0].snapshotView + @get:Deprecated("Use [taskContainers] instead.") val firstItemInfo: ItemInfo get() = taskContainers[0].itemInfo @@ -1197,10 +1204,10 @@ constructor( this, container.task, container.iconView.drawable, - container.thumbnailViewDeprecated, - container.thumbnailViewDeprecated.thumbnail, /* intent */ - null, /* user */ - null, + container.snapshotView, + container.thumbnail, + /* intent */ null, + /* user */ null, container.itemInfo ) } @@ -1512,6 +1519,10 @@ constructor( gridTranslationY = 0f boxTranslationY = 0f nonGridPivotTranslationX = 0f + taskContainers.forEach { + it.snapshotView.translationX = 0f + it.snapshotView.translationY = 0f + } resetViewTransforms() } @@ -1537,10 +1548,6 @@ constructor( alpha = stableAlpha setIconScaleAndDim(1f) setColorTint(0f, 0) - if (!enableRefactorTaskThumbnail()) { - // TODO(b/335399428) add split select functionality to new TTV - taskContainers.forEach { it.thumbnailViewDeprecated.resetViewTransforms() } - } } private fun getGridTrans(endTranslation: Float) = @@ -1624,6 +1631,18 @@ constructor( val snapshotView: View get() = thumbnailView ?: thumbnailViewDeprecated + // TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel + val thumbnail: Bitmap? + get() = thumbnailViewDeprecated.thumbnail + + // TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel + val isRealSnapshot: Boolean + get() = thumbnailViewDeprecated.isRealSnapshot() + + // TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel + val scaledInsets: Insets + get() = thumbnailViewDeprecated.scaledInsets + /** Builds proto for logging */ val itemInfo: WorkspaceItemInfo get() = diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt index d40f8ab389..c8893ad07e 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt @@ -33,7 +33,6 @@ import com.android.launcher3.taskbar.TaskbarActivityContext import com.android.launcher3.util.SplitConfigurationOptions import com.android.quickstep.views.GroupedTaskView import com.android.quickstep.views.IconView -import com.android.quickstep.views.TaskThumbnailViewDeprecated import com.android.quickstep.views.TaskView import com.android.quickstep.views.TaskView.TaskContainer import com.android.systemui.shared.recents.model.Task @@ -59,7 +58,7 @@ class SplitAnimationControllerTest { private val mockSplitSelectStateController: SplitSelectStateController = mock() // TaskView private val mockTaskView: TaskView = mock() - private val mockThumbnailView: TaskThumbnailViewDeprecated = mock() + private val mockSnapshotView: View = mock() private val mockBitmap: Bitmap = mock() private val mockIconView: IconView = mock() private val mockTaskViewDrawable: Drawable = mock() @@ -87,8 +86,8 @@ class SplitAnimationControllerTest { @Before fun setup() { - whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView) - whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap) + whenever(mockTaskContainer.snapshotView).thenReturn(mockSnapshotView) + whenever(mockTaskContainer.thumbnail).thenReturn(mockBitmap) whenever(mockTaskContainer.iconView).thenReturn(mockIconView) whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable) whenever(mockTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer }) @@ -180,7 +179,6 @@ class SplitAnimationControllerTest { whenever(mockTaskContainer.task).thenReturn(mockTask) whenever(mockTaskContainer.iconView).thenReturn(mockIconView) - whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView) whenever(mockTask.getKey()).thenReturn(mockTaskKey) whenever(mockTaskKey.getId()).thenReturn(taskId) whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)