From c90fcf26c453493386f31ed6cc495301eb99c6f2 Mon Sep 17 00:00:00 2001 From: Yuichiro Hanada Date: Mon, 28 Oct 2024 16:44:03 +0900 Subject: [PATCH] Move the animator for the minimization to WMShell to share the animator with the minimize button. Flag: EXEMPT refactoring Bug: 369349585 Test: manual Change-Id: I42325913313a85e1086ab6bc4151f60cb3bc4605 --- .../desktop/DesktopAppLaunchTransition.kt | 46 ++---- .../launcher3/desktop/WindowAnimator.kt | 100 ------------- .../quickstep/desktop/WindowAnimatorTest.kt | 139 ------------------ 3 files changed, 10 insertions(+), 275 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt delete mode 100644 quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt index dd2ff2d580..6916a1d26a 100644 --- a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt +++ b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt @@ -32,6 +32,8 @@ import android.window.TransitionInfo.Change import androidx.core.animation.addListener import com.android.app.animation.Interpolators import com.android.quickstep.RemoteRunnable +import com.android.wm.shell.shared.animation.MinimizeAnimator +import com.android.wm.shell.shared.animation.WindowAnimator import java.util.concurrent.Executor /** @@ -77,7 +79,13 @@ class DesktopAppLaunchTransition(private val context: Context, private val mainE val launchAnimator = createLaunchAnimator(getLaunchChange(info), transaction, finishCallback) val minimizeChange = getMinimizeChange(info) ?: return listOf(launchAnimator) - val minimizeAnimator = createMinimizeAnimator(minimizeChange, transaction, finishCallback) + val minimizeAnimator = + MinimizeAnimator.create( + context.resources.displayMetrics, + minimizeChange, + transaction, + finishCallback, + ) return listOf(launchAnimator, minimizeAnimator) } @@ -96,7 +104,7 @@ class DesktopAppLaunchTransition(private val context: Context, private val mainE ): Animator { val boundsAnimator = WindowAnimator.createBoundsAnimator( - context, + context.resources.displayMetrics, launchBoundsAnimationDef, change, transaction, @@ -115,32 +123,6 @@ class DesktopAppLaunchTransition(private val context: Context, private val mainE } } - private fun createMinimizeAnimator( - change: Change, - transaction: Transaction, - onAnimFinish: (Animator) -> Unit, - ): Animator { - val boundsAnimator = - WindowAnimator.createBoundsAnimator( - context, - minimizeBoundsAnimationDef, - change, - transaction, - ) - val alphaAnimator = - ValueAnimator.ofFloat(1f, 0f).apply { - duration = MINIMIZE_ANIM_ALPHA_DURATION_MS - interpolator = Interpolators.LINEAR - addUpdateListener { animation -> - transaction.setAlpha(change.leash, animation.animatedValue as Float).apply() - } - } - return AnimatorSet().apply { - playTogether(boundsAnimator, alphaAnimator) - addListener(onEnd = { animation -> onAnimFinish(animation) }) - } - } - companion object { private val LAUNCH_CHANGE_MODES = intArrayOf(TRANSIT_OPEN, TRANSIT_TO_FRONT) @@ -154,13 +136,5 @@ class DesktopAppLaunchTransition(private val context: Context, private val mainE startScale = 0.97f, interpolator = Interpolators.STANDARD_DECELERATE, ) - - private val minimizeBoundsAnimationDef = - WindowAnimator.BoundsAnimationParams( - durationMs = 200, - endOffsetYDp = 12f, - endScale = 0.97f, - interpolator = Interpolators.STANDARD_ACCELERATE, - ) } } diff --git a/quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt b/quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt deleted file mode 100644 index 1a99a36b4c..0000000000 --- a/quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.desktop - -import android.animation.RectEvaluator -import android.animation.ValueAnimator -import android.content.Context -import android.graphics.Rect -import android.util.TypedValue -import android.view.SurfaceControl -import android.view.animation.Interpolator -import android.window.TransitionInfo - -/** Creates animations that can be applied to windows/surfaces. */ -object WindowAnimator { - - /** Parameters defining a window bounds animation. */ - data class BoundsAnimationParams( - val durationMs: Long, - val startOffsetYDp: Float = 0f, - val endOffsetYDp: Float = 0f, - val startScale: Float = 1f, - val endScale: Float = 1f, - val interpolator: Interpolator, - ) - - /** - * Creates an animator to reposition and scale the bounds of the leash of the given change. - * - * @param boundsAnimDef the parameters for the animation itself (duration, scale, position) - * @param change the change to which the animation should be applied - * @param transaction the transaction to apply the animation to - */ - fun createBoundsAnimator( - context: Context, - boundsAnimDef: BoundsAnimationParams, - change: TransitionInfo.Change, - transaction: SurfaceControl.Transaction, - ): ValueAnimator { - val startBounds = - createBounds( - context, - change.startAbsBounds, - boundsAnimDef.startScale, - boundsAnimDef.startOffsetYDp, - ) - val leash = change.leash - val endBounds = - createBounds( - context, - change.startAbsBounds, - boundsAnimDef.endScale, - boundsAnimDef.endOffsetYDp, - ) - return ValueAnimator.ofObject(RectEvaluator(), startBounds, endBounds).apply { - duration = boundsAnimDef.durationMs - interpolator = boundsAnimDef.interpolator - addUpdateListener { animation -> - val animBounds = animation.animatedValue as Rect - val animScale = 1 - (1 - boundsAnimDef.endScale) * animation.animatedFraction - transaction - .setPosition(leash, animBounds.left.toFloat(), animBounds.top.toFloat()) - .setScale(leash, animScale, animScale) - .apply() - } - } - } - - private fun createBounds(context: Context, origBounds: Rect, scale: Float, offsetYDp: Float) = - Rect(origBounds).apply { - check(scale in 0.0..1.0) - // Scale the bounds down with an anchor in the center - inset( - (origBounds.width().toFloat() * (1 - scale) / 2).toInt(), - (origBounds.height().toFloat() * (1 - scale) / 2).toInt(), - ) - val offsetYPx = - TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - offsetYDp, - context.resources.displayMetrics, - ) - .toInt() - offset(/* dx= */ 0, offsetYPx) - } -} diff --git a/quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt b/quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt deleted file mode 100644 index e5e6df3b1e..0000000000 --- a/quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.quickstep.desktop - -import android.animation.ValueAnimator -import android.content.Context -import android.content.res.Resources -import android.graphics.Rect -import android.util.DisplayMetrics -import android.view.SurfaceControl -import android.window.TransitionInfo -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread -import com.android.app.animation.Interpolators -import com.android.launcher3.desktop.WindowAnimator -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any -import org.mockito.ArgumentMatchers.anyFloat -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever - -@SmallTest -@RunWith(AndroidJUnit4::class) -class WindowAnimatorTest { - - private val context = mock() - private val resources = mock() - private val transaction = mock() - private val change = mock() - private val leash = mock() - - private val displayMetrics = DisplayMetrics().apply { density = 1f } - - @Before - fun setup() { - whenever(context.resources).thenReturn(resources) - whenever(resources.displayMetrics).thenReturn(displayMetrics) - whenever(change.leash).thenReturn(leash) - whenever(change.startAbsBounds).thenReturn(START_BOUNDS) - whenever(transaction.setPosition(any(), anyFloat(), anyFloat())).thenReturn(transaction) - whenever(transaction.setScale(any(), anyFloat(), anyFloat())).thenReturn(transaction) - } - - @Test - fun createBoundsAnimator_returnsCorrectDefaultAnimatorParams() = runOnUiThread { - val boundsAnimParams = - WindowAnimator.BoundsAnimationParams( - durationMs = 100L, - interpolator = Interpolators.STANDARD_ACCELERATE, - ) - - val valueAnimator = - WindowAnimator.createBoundsAnimator(context, boundsAnimParams, change, transaction) - - assertThat(valueAnimator.duration).isEqualTo(100L) - assertThat(valueAnimator.interpolator).isEqualTo(Interpolators.STANDARD_ACCELERATE) - assertStartAndEndBounds(valueAnimator, startBounds = START_BOUNDS, endBounds = START_BOUNDS) - } - - @Test - fun createBoundsAnimator_startScaleAndOffset_returnsCorrectBounds() = runOnUiThread { - val bounds = Rect(/* left= */ 100, /* top= */ 200, /* right= */ 300, /* bottom= */ 400) - whenever(change.startAbsBounds).thenReturn(bounds) - val boundsAnimParams = - WindowAnimator.BoundsAnimationParams( - durationMs = 100L, - startOffsetYDp = 10f, - startScale = 0.5f, - interpolator = Interpolators.STANDARD_ACCELERATE, - ) - - val valueAnimator = - WindowAnimator.createBoundsAnimator(context, boundsAnimParams, change, transaction) - - assertStartAndEndBounds( - valueAnimator, - startBounds = - Rect(/* left= */ 150, /* top= */ 260, /* right= */ 250, /* bottom= */ 360), - endBounds = bounds, - ) - } - - @Test - fun createBoundsAnimator_endScaleAndOffset_returnsCorrectBounds() = runOnUiThread { - val bounds = Rect(/* left= */ 100, /* top= */ 200, /* right= */ 300, /* bottom= */ 400) - whenever(change.startAbsBounds).thenReturn(bounds) - val boundsAnimParams = - WindowAnimator.BoundsAnimationParams( - durationMs = 100L, - endOffsetYDp = 10f, - endScale = 0.5f, - interpolator = Interpolators.STANDARD_ACCELERATE, - ) - - val valueAnimator = - WindowAnimator.createBoundsAnimator(context, boundsAnimParams, change, transaction) - - assertStartAndEndBounds( - valueAnimator, - startBounds = bounds, - endBounds = Rect(/* left= */ 150, /* top= */ 260, /* right= */ 250, /* bottom= */ 360), - ) - } - - private fun assertStartAndEndBounds( - valueAnimator: ValueAnimator, - startBounds: Rect, - endBounds: Rect, - ) { - valueAnimator.start() - valueAnimator.animatedValue - assertThat(valueAnimator.animatedValue).isEqualTo(startBounds) - valueAnimator.end() - assertThat(valueAnimator.animatedValue).isEqualTo(endBounds) - } - - companion object { - private val START_BOUNDS = - Rect(/* left= */ 10, /* top= */ 20, /* right= */ 30, /* bottom= */ 40) - } -}