diff options
18 files changed, 1983 insertions, 79 deletions
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 74d61ca199dd..089782c5e82a 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -249,6 +249,9 @@ android_library { resource_dirs: [ "tests/res", ], + asset_dirs: [ + "tests/goldens", + ], static_libs: [ "SystemUI-res", "WifiTrackerLib", @@ -349,6 +352,8 @@ android_library { "androidx.test.ext.junit", "androidx.test.ext.truth", "kotlin-test", + "platform-screenshot-diff-core", + "PlatformMotionTesting", "SystemUICustomizationTestUtils", "androidx.compose.runtime_runtime", "kosmos", diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp index a6d750f8f6b4..1ce3be897259 100644 --- a/packages/SystemUI/animation/Android.bp +++ b/packages/SystemUI/animation/Android.bp @@ -48,6 +48,7 @@ android_library { "SystemUIShaderLib", "WindowManager-Shell-shared", "animationlib", + "com_android_systemui_shared_flags_lib", ], manifest: "AndroidManifest.xml", diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt index ea1cb3441215..9ce30fd0c6cb 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt @@ -790,7 +790,7 @@ class ActivityTransitionAnimator( controller, endState, windowBackgroundColor, - fadeOutWindowBackgroundLayer = !controller.isBelowAnimatingWindow, + fadeWindowBackgroundLayer = !controller.isBelowAnimatingWindow, drawHole = !controller.isBelowAnimatingWindow, ) } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt index 24cc8a4cfcec..b89ebfcb3675 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt @@ -916,6 +916,12 @@ private class AnimatedDialog( endController.transitionContainer = value } + // We tell TransitionController that this is always a launch, and handle the launch + // vs return logic internally. + // TODO(b/323863002): maybe move the launch vs return logic out of this class and + // delegate it to TransitionController? + override val isLaunching: Boolean = true + override fun createAnimatorState(): TransitionAnimator.State { return startController.createAnimatorState() } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt index 3f57f88a13d3..9ad0fc53648f 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewTransitionAnimatorController.kt @@ -64,6 +64,7 @@ constructor( private var interactionJankMonitor: InteractionJankMonitor = InteractionJankMonitor.getInstance(), ) : ActivityTransitionAnimator.Controller { + override val isLaunching: Boolean = true /** The container to which we will add the ghost view and expanding background. */ override var transitionContainer = ghostedView.rootView as ViewGroup diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt index 5e4276ce3dd2..9bf6b346d16d 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt @@ -28,7 +28,9 @@ import android.util.MathUtils import android.view.View import android.view.ViewGroup import android.view.animation.Interpolator +import androidx.annotation.VisibleForTesting import com.android.app.animation.Interpolators.LINEAR +import com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary import kotlin.math.roundToInt private const val TAG = "TransitionAnimator" @@ -70,13 +72,14 @@ class TransitionAnimator(private val timings: Timings, private val interpolators interface Controller { /** * The container in which the view that started the animation will be animating together - * with the opening window. + * with the opening or closing window. * * This will be used to: * - Get the associated [Context]. - * - Compute whether we are expanding fully above the transition container. - * - Get to overlay to which we initially put the window background layer, until the opening - * window is made visible (see [openingWindowSyncView]). + * - Compute whether we are expanding to or contracting from fully above the transition + * container. + * - Get the overlay into which we put the window background layer, while the animating + * window is not visible (see [openingWindowSyncView]). * * This container can be changed to force this [Controller] to animate the expanding view * inside a different location, for instance to ensure correct layering during the @@ -84,12 +87,17 @@ class TransitionAnimator(private val timings: Timings, private val interpolators */ var transitionContainer: ViewGroup + /** Whether the animation being controlled is a launch or a return. */ + val isLaunching: Boolean + /** - * The [View] with which the opening app window should be synchronized with once it starts - * to be visible. + * If [isLaunching], the [View] with which the opening app window should be synchronized + * once it starts to be visible. Otherwise, the [View] with which the closing app window + * should be synchronized until it stops being visible. * * We will also move the window background layer to this view's overlay once the opening - * window is visible. + * window is visible (if [isLaunching]), or from this view's overlay once the closing window + * stop being visible (if ![isLaunching]). * * If null, this will default to [transitionContainer]. */ @@ -203,17 +211,56 @@ class TransitionAnimator(private val timings: Timings, private val interpolators * layer with [windowBackgroundColor] will fade in then (optionally) fade out above the * expanding view, and should be the same background color as the opening (or closing) window. * - * If [fadeOutWindowBackgroundLayer] is true, then this intermediary layer will fade out during - * the second half of the animation, and will have SRC blending mode (ultimately punching a hole - * in the [transition container][Controller.transitionContainer]) iff [drawHole] is true. + * If [fadeWindowBackgroundLayer] is true, then this intermediary layer will fade out during the + * second half of the animation (if [Controller.isLaunching] or fade in during the first half of + * the animation (if ![Controller.isLaunching]), and will have SRC blending mode (ultimately + * punching a hole in the [transition container][Controller.transitionContainer]) iff [drawHole] + * is true. */ fun startAnimation( controller: Controller, endState: State, windowBackgroundColor: Int, - fadeOutWindowBackgroundLayer: Boolean = true, + fadeWindowBackgroundLayer: Boolean = true, drawHole: Boolean = false, ): Animation { + if (!controller.isLaunching) checkReturnAnimationFrameworkFlag() + + // We add an extra layer with the same color as the dialog/app splash screen background + // color, which is usually the same color of the app background. We first fade in this layer + // to hide the expanding view, then we fade it out with SRC mode to draw a hole in the + // transition container and reveal the opening window. + val windowBackgroundLayer = + GradientDrawable().apply { + setColor(windowBackgroundColor) + alpha = 0 + } + + val animator = + createAnimator( + controller, + endState, + windowBackgroundLayer, + fadeWindowBackgroundLayer, + drawHole + ) + animator.start() + + return object : Animation { + override fun cancel() { + animator.cancel() + } + } + } + + @VisibleForTesting + fun createAnimator( + controller: Controller, + endState: State, + windowBackgroundLayer: GradientDrawable, + fadeWindowBackgroundLayer: Boolean = true, + drawHole: Boolean = false + ): ValueAnimator { val state = controller.createAnimatorState() // Start state. @@ -255,31 +302,24 @@ class TransitionAnimator(private val timings: Timings, private val interpolators val transitionContainer = controller.transitionContainer val isExpandingFullyAbove = isExpandingFullyAbove(transitionContainer, endState) - // We add an extra layer with the same color as the dialog/app splash screen background - // color, which is usually the same color of the app background. We first fade in this layer - // to hide the expanding view, then we fade it out with SRC mode to draw a hole in the - // transition container and reveal the opening window. - val windowBackgroundLayer = - GradientDrawable().apply { - setColor(windowBackgroundColor) - alpha = 0 - } - // Update state. val animator = ValueAnimator.ofFloat(0f, 1f) animator.duration = timings.totalDuration animator.interpolator = LINEAR // Whether we should move the [windowBackgroundLayer] into the overlay of - // [Controller.openingWindowSyncView] once the opening app window starts to be visible. + // [Controller.openingWindowSyncView] once the opening app window starts to be visible, or + // from it once the closing app window stops being visible. + // This is necessary as a one-off sync so we can avoid syncing at every frame, especially + // in complex interactions like launching an activity from a dialog. See + // b/214961273#comment2 for more details. val openingWindowSyncView = controller.openingWindowSyncView val openingWindowSyncViewOverlay = openingWindowSyncView?.overlay - val moveBackgroundLayerWhenAppIsVisible = + val moveBackgroundLayerWhenAppVisibilityChanges = openingWindowSyncView != null && openingWindowSyncView.viewRootImpl != controller.transitionContainer.viewRootImpl val transitionContainerOverlay = transitionContainer.overlay - var cancelled = false var movedBackgroundLayer = false animator.addListener( @@ -293,7 +333,11 @@ class TransitionAnimator(private val timings: Timings, private val interpolators // Add the drawable to the transition container overlay. Overlays always draw // drawables after views, so we know that it will be drawn above any view added // by the controller. - transitionContainerOverlay.add(windowBackgroundLayer) + if (controller.isLaunching || openingWindowSyncViewOverlay == null) { + transitionContainerOverlay.add(windowBackgroundLayer) + } else { + openingWindowSyncViewOverlay.add(windowBackgroundLayer) + } } override fun onAnimationEnd(animation: Animator) { @@ -303,7 +347,7 @@ class TransitionAnimator(private val timings: Timings, private val interpolators controller.onTransitionAnimationEnd(isExpandingFullyAbove) transitionContainerOverlay.remove(windowBackgroundLayer) - if (moveBackgroundLayerWhenAppIsVisible) { + if (moveBackgroundLayerWhenAppVisibilityChanges && controller.isLaunching) { openingWindowSyncViewOverlay?.remove(windowBackgroundLayer) } } @@ -311,12 +355,6 @@ class TransitionAnimator(private val timings: Timings, private val interpolators ) animator.addUpdateListener { animation -> - if (cancelled) { - // TODO(b/184121838): Cancel the animator directly instead of just skipping the - // update. - return@addUpdateListener - } - maybeUpdateEndState() // TODO(b/184121838): Use reverse interpolators to get the same path/arc as the non @@ -338,20 +376,34 @@ class TransitionAnimator(private val timings: Timings, private val interpolators state.bottomCornerRadius = MathUtils.lerp(startBottomCornerRadius, endBottomCornerRadius, progress) - // The expanding view can/should be hidden once it is completely covered by the opening - // window. state.visible = - getProgress( - timings, - linearProgress, - timings.contentBeforeFadeOutDelay, - timings.contentBeforeFadeOutDuration - ) < 1 - - if (moveBackgroundLayerWhenAppIsVisible && !state.visible && !movedBackgroundLayer) { - // The expanding view is not visible, so the opening app is visible. If this is the - // first frame when it happens, trigger a one-off sync and move the background layer - // in its new container. + if (controller.isLaunching) { + // The expanding view can/should be hidden once it is completely covered by the + // opening window. + getProgress( + timings, + linearProgress, + timings.contentBeforeFadeOutDelay, + timings.contentBeforeFadeOutDuration + ) < 1 + } else { + getProgress( + timings, + linearProgress, + timings.contentAfterFadeInDelay, + timings.contentAfterFadeInDuration + ) > 0 + } + + if ( + controller.isLaunching && + moveBackgroundLayerWhenAppVisibilityChanges && + !state.visible && + !movedBackgroundLayer + ) { + // The expanding view is not visible, so the opening app is visible. If this is + // the first frame when it happens, trigger a one-off sync and move the + // background layer in its new container. movedBackgroundLayer = true transitionContainerOverlay.remove(windowBackgroundLayer) @@ -362,6 +414,25 @@ class TransitionAnimator(private val timings: Timings, private val interpolators openingWindowSyncView, then = {} ) + } else if ( + !controller.isLaunching && + moveBackgroundLayerWhenAppVisibilityChanges && + state.visible && + !movedBackgroundLayer + ) { + // The contracting view is now visible, so the closing app is not. If this is + // the first frame when it happens, trigger a one-off sync and move the + // background layer in its new container. + movedBackgroundLayer = true + + openingWindowSyncViewOverlay!!.remove(windowBackgroundLayer) + transitionContainerOverlay.add(windowBackgroundLayer) + + ViewRootSync.synchronizeNextDraw( + openingWindowSyncView, + transitionContainer, + then = {} + ) } val container = @@ -376,19 +447,14 @@ class TransitionAnimator(private val timings: Timings, private val interpolators state, linearProgress, container, - fadeOutWindowBackgroundLayer, - drawHole + fadeWindowBackgroundLayer, + drawHole, + controller.isLaunching ) controller.onTransitionAnimationProgress(state, progress, linearProgress) } - animator.start() - return object : Animation { - override fun cancel() { - cancelled = true - animator.cancel() - } - } + return animator } /** Return whether we are expanding fully above the [transitionContainer]. */ @@ -405,8 +471,9 @@ class TransitionAnimator(private val timings: Timings, private val interpolators state: State, linearProgress: Float, transitionContainer: View, - fadeOutWindowBackgroundLayer: Boolean, - drawHole: Boolean + fadeWindowBackgroundLayer: Boolean, + drawHole: Boolean, + isLaunching: Boolean ) { // Update position. transitionContainer.getLocationOnScreen(transitionContainerLocation) @@ -437,27 +504,64 @@ class TransitionAnimator(private val timings: Timings, private val interpolators timings.contentBeforeFadeOutDelay, timings.contentBeforeFadeOutDuration ) - if (fadeInProgress < 1) { - val alpha = - interpolators.contentBeforeFadeOutInterpolator.getInterpolation(fadeInProgress) - drawable.alpha = (alpha * 0xFF).roundToInt() - } else if (fadeOutWindowBackgroundLayer) { - val fadeOutProgress = - getProgress( - timings, - linearProgress, - timings.contentAfterFadeInDelay, - timings.contentAfterFadeInDuration - ) - val alpha = - 1 - interpolators.contentAfterFadeInInterpolator.getInterpolation(fadeOutProgress) - drawable.alpha = (alpha * 0xFF).roundToInt() - if (drawHole) { - drawable.setXfermode(SRC_MODE) + if (isLaunching) { + if (fadeInProgress < 1) { + val alpha = + interpolators.contentBeforeFadeOutInterpolator.getInterpolation(fadeInProgress) + drawable.alpha = (alpha * 0xFF).roundToInt() + } else if (fadeWindowBackgroundLayer) { + val fadeOutProgress = + getProgress( + timings, + linearProgress, + timings.contentAfterFadeInDelay, + timings.contentAfterFadeInDuration + ) + val alpha = + 1 - + interpolators.contentAfterFadeInInterpolator.getInterpolation( + fadeOutProgress + ) + drawable.alpha = (alpha * 0xFF).roundToInt() + + if (drawHole) { + drawable.setXfermode(SRC_MODE) + } + } else { + drawable.alpha = 0xFF } } else { - drawable.alpha = 0xFF + if (fadeInProgress < 1 && fadeWindowBackgroundLayer) { + val alpha = + interpolators.contentBeforeFadeOutInterpolator.getInterpolation(fadeInProgress) + drawable.alpha = (alpha * 0xFF).roundToInt() + + if (drawHole) { + drawable.setXfermode(SRC_MODE) + } + } else { + val fadeOutProgress = + getProgress( + timings, + linearProgress, + timings.contentAfterFadeInDelay, + timings.contentAfterFadeInDuration + ) + val alpha = + 1 - + interpolators.contentAfterFadeInInterpolator.getInterpolation( + fadeOutProgress + ) + drawable.alpha = (alpha * 0xFF).roundToInt() + drawable.setXfermode(null) + } + } + } + + private fun checkReturnAnimationFrameworkFlag() { + check(returnAnimationFrameworkLibrary()) { + "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag is disabled" } } } diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt index 974ee3a40903..c7f0a965206e 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt @@ -168,6 +168,9 @@ internal class ExpandableControllerImpl( override var transitionContainer: ViewGroup = composeViewRoot.rootView as ViewGroup + // TODO(b/323863002): update to be dependant on usage. + override val isLaunching: Boolean = true + override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { animatorState.value = null } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 53aee5da0793..fb0d225419c9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -178,8 +178,6 @@ import com.android.systemui.util.time.SystemClock; import com.android.systemui.wallpapers.data.repository.WallpaperRepository; import com.android.wm.shell.keyguard.KeyguardTransitions; -import dagger.Lazy; - import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -189,6 +187,7 @@ import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; +import dagger.Lazy; import kotlinx.coroutines.CoroutineDispatcher; /** @@ -964,6 +963,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, @VisibleForTesting final ActivityTransitionAnimator.Controller mOccludeAnimationController = new ActivityTransitionAnimator.Controller() { + private boolean mIsLaunching = true; + + @Override + public boolean isLaunching() { + return mIsLaunching; + } + @Override public void onTransitionAnimationStart(boolean isExpandingFullyAbove) { mOccludeAnimationPlaying = true; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt index aab90c378a19..585bd6adf11f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt @@ -263,6 +263,7 @@ constructor( @VisibleForTesting val occludeAnimationController: ActivityTransitionAnimator.Controller = object : ActivityTransitionAnimator.Controller { + override val isLaunching: Boolean = true override var transitionContainer: ViewGroup get() = keyguardViewController.get().getViewRootImpl().view as ViewGroup diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt index eb0870a5de44..2b7df7dc937d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt @@ -75,6 +75,8 @@ class NotificationTransitionAnimatorController( private val notificationEntry = notification.entry private val notificationKey = notificationEntry.sbn.key + override val isLaunching: Boolean = true + override var transitionContainer: ViewGroup get() = notification.rootView as ViewGroup set(ignored) { diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index 572a6c12f3e1..0dbbe63b63bd 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -224,6 +224,5 @@ <instrumentation android:name="android.testing.TestableInstrumentation" android:targetPackage="com.android.systemui.tests" - android:label="Tests for SystemUI"> - </instrumentation> + android:label="Tests for SystemUI" /> </manifest> diff --git a/packages/SystemUI/tests/AndroidTest.xml b/packages/SystemUI/tests/AndroidTest.xml index cd2a62de1acc..2de5faf2be8c 100644 --- a/packages/SystemUI/tests/AndroidTest.xml +++ b/packages/SystemUI/tests/AndroidTest.xml @@ -23,6 +23,15 @@ <option name="force-root" value="true" /> </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <option name="screen-always-on" value="on" /> + </target_preparer> + + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="run-command" value="input keyevent KEYCODE_WAKEUP" /> + <option name="run-command" value="wm dismiss-keyguard" /> + </target_preparer> + <option name="test-suite-tag" value="apct" /> <option name="test-suite-tag" value="framework-base-presubmit" /> <option name="test-tag" value="SystemUITests" /> diff --git a/packages/SystemUI/tests/goldens/backgroundAnimationWithoutFade_whenLaunching.json b/packages/SystemUI/tests/goldens/backgroundAnimationWithoutFade_whenLaunching.json new file mode 100644 index 000000000000..60bff17c8541 --- /dev/null +++ b/packages/SystemUI/tests/goldens/backgroundAnimationWithoutFade_whenLaunching.json @@ -0,0 +1,393 @@ +{ + "frame_ids": [ + "before", + 0, + 26, + 52, + 78, + 105, + 131, + 157, + 184, + 210, + 236, + 263, + 289, + 315, + 342, + 368, + 394, + 421, + 447, + 473, + 500 + ], + "features": [ + { + "name": "bounds", + "type": "rect", + "data_points": [ + { + "left": 0, + "top": 0, + "right": 0, + "bottom": 0 + }, + { + "left": 100, + "top": 300, + "right": 200, + "bottom": 400 + }, + { + "left": 98, + "top": 293, + "right": 203, + "bottom": 407 + }, + { + "left": 91, + "top": 269, + "right": 213, + "bottom": 430 + }, + { + "left": 71, + "top": 206, + "right": 240, + "bottom": 491 + }, + { + "left": 34, + "top": 98, + "right": 283, + "bottom": 595 + }, + { + "left": 22, + "top": 63, + "right": 296, + "bottom": 629 + }, + { + "left": 15, + "top": 44, + "right": 303, + "bottom": 648 + }, + { + "left": 11, + "top": 32, + "right": 308, + "bottom": 659 + }, + { + "left": 8, + "top": 23, + "right": 311, + "bottom": 667 + }, + { + "left": 6, + "top": 18, + "right": 313, + "bottom": 673 + }, + { + "left": 5, + "top": 13, + "right": 315, + "bottom": 677 + }, + { + "left": 3, + "top": 9, + "right": 316, + "bottom": 681 + }, + { + "left": 2, + "top": 7, + "right": 317, + "bottom": 683 + }, + { + "left": 2, + "top": 5, + "right": 318, + "bottom": 685 + }, + { + "left": 1, + "top": 3, + "right": 319, + "bottom": 687 + }, + { + "left": 1, + "top": 2, + "right": 319, + "bottom": 688 + }, + { + "left": 0, + "top": 1, + "right": 320, + "bottom": 689 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + } + ] + }, + { + "name": "corner_radii", + "type": "cornerRadii", + "data_points": [ + null, + { + "top_left_x": 10, + "top_left_y": 10, + "top_right_x": 10, + "top_right_y": 10, + "bottom_right_x": 20, + "bottom_right_y": 20, + "bottom_left_x": 20, + "bottom_left_y": 20 + }, + { + "top_left_x": 9.762664, + "top_left_y": 9.762664, + "top_right_x": 9.762664, + "top_right_y": 9.762664, + "bottom_right_x": 19.525328, + "bottom_right_y": 19.525328, + "bottom_left_x": 19.525328, + "bottom_left_y": 19.525328 + }, + { + "top_left_x": 8.969244, + "top_left_y": 8.969244, + "top_right_x": 8.969244, + "top_right_y": 8.969244, + "bottom_right_x": 17.938488, + "bottom_right_y": 17.938488, + "bottom_left_x": 17.938488, + "bottom_left_y": 17.938488 + }, + { + "top_left_x": 6.8709626, + "top_left_y": 6.8709626, + "top_right_x": 6.8709626, + "top_right_y": 6.8709626, + "bottom_right_x": 13.741925, + "bottom_right_y": 13.741925, + "bottom_left_x": 13.741925, + "bottom_left_y": 13.741925 + }, + { + "top_left_x": 3.260561, + "top_left_y": 3.260561, + "top_right_x": 3.260561, + "top_right_y": 3.260561, + "bottom_right_x": 6.521122, + "bottom_right_y": 6.521122, + "bottom_left_x": 6.521122, + "bottom_left_y": 6.521122 + }, + { + "top_left_x": 2.0915751, + "top_left_y": 2.0915751, + "top_right_x": 2.0915751, + "top_right_y": 2.0915751, + "bottom_right_x": 4.1831503, + "bottom_right_y": 4.1831503, + "bottom_left_x": 4.1831503, + "bottom_left_y": 4.1831503 + }, + { + "top_left_x": 1.4640827, + "top_left_y": 1.4640827, + "top_right_x": 1.4640827, + "top_right_y": 1.4640827, + "bottom_right_x": 2.9281654, + "bottom_right_y": 2.9281654, + "bottom_left_x": 2.9281654, + "bottom_left_y": 2.9281654 + }, + { + "top_left_x": 1.057313, + "top_left_y": 1.057313, + "top_right_x": 1.057313, + "top_right_y": 1.057313, + "bottom_right_x": 2.114626, + "bottom_right_y": 2.114626, + "bottom_left_x": 2.114626, + "bottom_left_y": 2.114626 + }, + { + "top_left_x": 0.7824335, + "top_left_y": 0.7824335, + "top_right_x": 0.7824335, + "top_right_y": 0.7824335, + "bottom_right_x": 1.564867, + "bottom_right_y": 1.564867, + "bottom_left_x": 1.564867, + "bottom_left_y": 1.564867 + }, + { + "top_left_x": 0.5863056, + "top_left_y": 0.5863056, + "top_right_x": 0.5863056, + "top_right_y": 0.5863056, + "bottom_right_x": 1.1726112, + "bottom_right_y": 1.1726112, + "bottom_left_x": 1.1726112, + "bottom_left_y": 1.1726112 + }, + { + "top_left_x": 0.4332962, + "top_left_y": 0.4332962, + "top_right_x": 0.4332962, + "top_right_y": 0.4332962, + "bottom_right_x": 0.8665924, + "bottom_right_y": 0.8665924, + "bottom_left_x": 0.8665924, + "bottom_left_y": 0.8665924 + }, + { + "top_left_x": 0.3145876, + "top_left_y": 0.3145876, + "top_right_x": 0.3145876, + "top_right_y": 0.3145876, + "bottom_right_x": 0.6291752, + "bottom_right_y": 0.6291752, + "bottom_left_x": 0.6291752, + "bottom_left_y": 0.6291752 + }, + { + "top_left_x": 0.22506618, + "top_left_y": 0.22506618, + "top_right_x": 0.22506618, + "top_right_y": 0.22506618, + "bottom_right_x": 0.45013237, + "bottom_right_y": 0.45013237, + "bottom_left_x": 0.45013237, + "bottom_left_y": 0.45013237 + }, + { + "top_left_x": 0.15591621, + "top_left_y": 0.15591621, + "top_right_x": 0.15591621, + "top_right_y": 0.15591621, + "bottom_right_x": 0.31183243, + "bottom_right_y": 0.31183243, + "bottom_left_x": 0.31183243, + "bottom_left_y": 0.31183243 + }, + { + "top_left_x": 0.100948334, + "top_left_y": 0.100948334, + "top_right_x": 0.100948334, + "top_right_y": 0.100948334, + "bottom_right_x": 0.20189667, + "bottom_right_y": 0.20189667, + "bottom_left_x": 0.20189667, + "bottom_left_y": 0.20189667 + }, + { + "top_left_x": 0.06496239, + "top_left_y": 0.06496239, + "top_right_x": 0.06496239, + "top_right_y": 0.06496239, + "bottom_right_x": 0.12992477, + "bottom_right_y": 0.12992477, + "bottom_left_x": 0.12992477, + "bottom_left_y": 0.12992477 + }, + { + "top_left_x": 0.03526497, + "top_left_y": 0.03526497, + "top_right_x": 0.03526497, + "top_right_y": 0.03526497, + "bottom_right_x": 0.07052994, + "bottom_right_y": 0.07052994, + "bottom_left_x": 0.07052994, + "bottom_left_y": 0.07052994 + }, + { + "top_left_x": 0.014661789, + "top_left_y": 0.014661789, + "top_right_x": 0.014661789, + "top_right_y": 0.014661789, + "bottom_right_x": 0.029323578, + "bottom_right_y": 0.029323578, + "bottom_left_x": 0.029323578, + "bottom_left_y": 0.029323578 + }, + { + "top_left_x": 0.0041856766, + "top_left_y": 0.0041856766, + "top_right_x": 0.0041856766, + "top_right_y": 0.0041856766, + "bottom_right_x": 0.008371353, + "bottom_right_y": 0.008371353, + "bottom_left_x": 0.008371353, + "bottom_left_y": 0.008371353 + }, + { + "top_left_x": 0, + "top_left_y": 0, + "top_right_x": 0, + "top_right_y": 0, + "bottom_right_x": 0, + "bottom_right_y": 0, + "bottom_left_x": 0, + "bottom_left_y": 0 + } + ] + }, + { + "name": "alpha", + "type": "int", + "data_points": [ + 0, + 0, + 115, + 178, + 217, + 241, + 253, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255 + ] + } + ] +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/goldens/backgroundAnimationWithoutFade_whenReturning.json b/packages/SystemUI/tests/goldens/backgroundAnimationWithoutFade_whenReturning.json new file mode 100644 index 000000000000..ea768c0a04bd --- /dev/null +++ b/packages/SystemUI/tests/goldens/backgroundAnimationWithoutFade_whenReturning.json @@ -0,0 +1,393 @@ +{ + "frame_ids": [ + "before", + 0, + 26, + 52, + 78, + 105, + 131, + 157, + 184, + 210, + 236, + 263, + 289, + 315, + 342, + 368, + 394, + 421, + 447, + 473, + 500 + ], + "features": [ + { + "name": "bounds", + "type": "rect", + "data_points": [ + { + "left": 0, + "top": 0, + "right": 0, + "bottom": 0 + }, + { + "left": 100, + "top": 300, + "right": 200, + "bottom": 400 + }, + { + "left": 98, + "top": 293, + "right": 203, + "bottom": 407 + }, + { + "left": 91, + "top": 269, + "right": 213, + "bottom": 430 + }, + { + "left": 71, + "top": 206, + "right": 240, + "bottom": 491 + }, + { + "left": 34, + "top": 98, + "right": 283, + "bottom": 595 + }, + { + "left": 22, + "top": 63, + "right": 296, + "bottom": 629 + }, + { + "left": 15, + "top": 44, + "right": 303, + "bottom": 648 + }, + { + "left": 11, + "top": 32, + "right": 308, + "bottom": 659 + }, + { + "left": 8, + "top": 23, + "right": 311, + "bottom": 667 + }, + { + "left": 6, + "top": 18, + "right": 313, + "bottom": 673 + }, + { + "left": 5, + "top": 13, + "right": 315, + "bottom": 677 + }, + { + "left": 3, + "top": 9, + "right": 316, + "bottom": 681 + }, + { + "left": 2, + "top": 7, + "right": 317, + "bottom": 683 + }, + { + "left": 2, + "top": 5, + "right": 318, + "bottom": 685 + }, + { + "left": 1, + "top": 3, + "right": 319, + "bottom": 687 + }, + { + "left": 1, + "top": 2, + "right": 319, + "bottom": 688 + }, + { + "left": 0, + "top": 1, + "right": 320, + "bottom": 689 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + } + ] + }, + { + "name": "corner_radii", + "type": "cornerRadii", + "data_points": [ + null, + { + "top_left_x": 10, + "top_left_y": 10, + "top_right_x": 10, + "top_right_y": 10, + "bottom_right_x": 20, + "bottom_right_y": 20, + "bottom_left_x": 20, + "bottom_left_y": 20 + }, + { + "top_left_x": 9.762664, + "top_left_y": 9.762664, + "top_right_x": 9.762664, + "top_right_y": 9.762664, + "bottom_right_x": 19.525328, + "bottom_right_y": 19.525328, + "bottom_left_x": 19.525328, + "bottom_left_y": 19.525328 + }, + { + "top_left_x": 8.969244, + "top_left_y": 8.969244, + "top_right_x": 8.969244, + "top_right_y": 8.969244, + "bottom_right_x": 17.938488, + "bottom_right_y": 17.938488, + "bottom_left_x": 17.938488, + "bottom_left_y": 17.938488 + }, + { + "top_left_x": 6.8709626, + "top_left_y": 6.8709626, + "top_right_x": 6.8709626, + "top_right_y": 6.8709626, + "bottom_right_x": 13.741925, + "bottom_right_y": 13.741925, + "bottom_left_x": 13.741925, + "bottom_left_y": 13.741925 + }, + { + "top_left_x": 3.260561, + "top_left_y": 3.260561, + "top_right_x": 3.260561, + "top_right_y": 3.260561, + "bottom_right_x": 6.521122, + "bottom_right_y": 6.521122, + "bottom_left_x": 6.521122, + "bottom_left_y": 6.521122 + }, + { + "top_left_x": 2.0915751, + "top_left_y": 2.0915751, + "top_right_x": 2.0915751, + "top_right_y": 2.0915751, + "bottom_right_x": 4.1831503, + "bottom_right_y": 4.1831503, + "bottom_left_x": 4.1831503, + "bottom_left_y": 4.1831503 + }, + { + "top_left_x": 1.4640827, + "top_left_y": 1.4640827, + "top_right_x": 1.4640827, + "top_right_y": 1.4640827, + "bottom_right_x": 2.9281654, + "bottom_right_y": 2.9281654, + "bottom_left_x": 2.9281654, + "bottom_left_y": 2.9281654 + }, + { + "top_left_x": 1.057313, + "top_left_y": 1.057313, + "top_right_x": 1.057313, + "top_right_y": 1.057313, + "bottom_right_x": 2.114626, + "bottom_right_y": 2.114626, + "bottom_left_x": 2.114626, + "bottom_left_y": 2.114626 + }, + { + "top_left_x": 0.7824335, + "top_left_y": 0.7824335, + "top_right_x": 0.7824335, + "top_right_y": 0.7824335, + "bottom_right_x": 1.564867, + "bottom_right_y": 1.564867, + "bottom_left_x": 1.564867, + "bottom_left_y": 1.564867 + }, + { + "top_left_x": 0.5863056, + "top_left_y": 0.5863056, + "top_right_x": 0.5863056, + "top_right_y": 0.5863056, + "bottom_right_x": 1.1726112, + "bottom_right_y": 1.1726112, + "bottom_left_x": 1.1726112, + "bottom_left_y": 1.1726112 + }, + { + "top_left_x": 0.4332962, + "top_left_y": 0.4332962, + "top_right_x": 0.4332962, + "top_right_y": 0.4332962, + "bottom_right_x": 0.8665924, + "bottom_right_y": 0.8665924, + "bottom_left_x": 0.8665924, + "bottom_left_y": 0.8665924 + }, + { + "top_left_x": 0.3145876, + "top_left_y": 0.3145876, + "top_right_x": 0.3145876, + "top_right_y": 0.3145876, + "bottom_right_x": 0.6291752, + "bottom_right_y": 0.6291752, + "bottom_left_x": 0.6291752, + "bottom_left_y": 0.6291752 + }, + { + "top_left_x": 0.22506618, + "top_left_y": 0.22506618, + "top_right_x": 0.22506618, + "top_right_y": 0.22506618, + "bottom_right_x": 0.45013237, + "bottom_right_y": 0.45013237, + "bottom_left_x": 0.45013237, + "bottom_left_y": 0.45013237 + }, + { + "top_left_x": 0.15591621, + "top_left_y": 0.15591621, + "top_right_x": 0.15591621, + "top_right_y": 0.15591621, + "bottom_right_x": 0.31183243, + "bottom_right_y": 0.31183243, + "bottom_left_x": 0.31183243, + "bottom_left_y": 0.31183243 + }, + { + "top_left_x": 0.100948334, + "top_left_y": 0.100948334, + "top_right_x": 0.100948334, + "top_right_y": 0.100948334, + "bottom_right_x": 0.20189667, + "bottom_right_y": 0.20189667, + "bottom_left_x": 0.20189667, + "bottom_left_y": 0.20189667 + }, + { + "top_left_x": 0.06496239, + "top_left_y": 0.06496239, + "top_right_x": 0.06496239, + "top_right_y": 0.06496239, + "bottom_right_x": 0.12992477, + "bottom_right_y": 0.12992477, + "bottom_left_x": 0.12992477, + "bottom_left_y": 0.12992477 + }, + { + "top_left_x": 0.03526497, + "top_left_y": 0.03526497, + "top_right_x": 0.03526497, + "top_right_y": 0.03526497, + "bottom_right_x": 0.07052994, + "bottom_right_y": 0.07052994, + "bottom_left_x": 0.07052994, + "bottom_left_y": 0.07052994 + }, + { + "top_left_x": 0.014661789, + "top_left_y": 0.014661789, + "top_right_x": 0.014661789, + "top_right_y": 0.014661789, + "bottom_right_x": 0.029323578, + "bottom_right_y": 0.029323578, + "bottom_left_x": 0.029323578, + "bottom_left_y": 0.029323578 + }, + { + "top_left_x": 0.0041856766, + "top_left_y": 0.0041856766, + "top_right_x": 0.0041856766, + "top_right_y": 0.0041856766, + "bottom_right_x": 0.008371353, + "bottom_right_y": 0.008371353, + "bottom_left_x": 0.008371353, + "bottom_left_y": 0.008371353 + }, + { + "top_left_x": 0, + "top_left_y": 0, + "top_right_x": 0, + "top_right_y": 0, + "bottom_right_x": 0, + "bottom_right_y": 0, + "bottom_left_x": 0, + "bottom_left_y": 0 + } + ] + }, + { + "name": "alpha", + "type": "int", + "data_points": [ + 0, + 255, + 255, + 255, + 255, + 255, + 255, + 239, + 183, + 135, + 91, + 53, + 23, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/goldens/backgroundAnimation_whenLaunching.json b/packages/SystemUI/tests/goldens/backgroundAnimation_whenLaunching.json new file mode 100644 index 000000000000..608e633d060b --- /dev/null +++ b/packages/SystemUI/tests/goldens/backgroundAnimation_whenLaunching.json @@ -0,0 +1,393 @@ +{ + "frame_ids": [ + "before", + 0, + 26, + 52, + 78, + 105, + 131, + 157, + 184, + 210, + 236, + 263, + 289, + 315, + 342, + 368, + 394, + 421, + 447, + 473, + 500 + ], + "features": [ + { + "name": "bounds", + "type": "rect", + "data_points": [ + { + "left": 0, + "top": 0, + "right": 0, + "bottom": 0 + }, + { + "left": 100, + "top": 300, + "right": 200, + "bottom": 400 + }, + { + "left": 98, + "top": 293, + "right": 203, + "bottom": 407 + }, + { + "left": 91, + "top": 269, + "right": 213, + "bottom": 430 + }, + { + "left": 71, + "top": 206, + "right": 240, + "bottom": 491 + }, + { + "left": 34, + "top": 98, + "right": 283, + "bottom": 595 + }, + { + "left": 22, + "top": 63, + "right": 296, + "bottom": 629 + }, + { + "left": 15, + "top": 44, + "right": 303, + "bottom": 648 + }, + { + "left": 11, + "top": 32, + "right": 308, + "bottom": 659 + }, + { + "left": 8, + "top": 23, + "right": 311, + "bottom": 667 + }, + { + "left": 6, + "top": 18, + "right": 313, + "bottom": 673 + }, + { + "left": 5, + "top": 13, + "right": 315, + "bottom": 677 + }, + { + "left": 3, + "top": 9, + "right": 316, + "bottom": 681 + }, + { + "left": 2, + "top": 7, + "right": 317, + "bottom": 683 + }, + { + "left": 2, + "top": 5, + "right": 318, + "bottom": 685 + }, + { + "left": 1, + "top": 3, + "right": 319, + "bottom": 687 + }, + { + "left": 1, + "top": 2, + "right": 319, + "bottom": 688 + }, + { + "left": 0, + "top": 1, + "right": 320, + "bottom": 689 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + } + ] + }, + { + "name": "corner_radii", + "type": "cornerRadii", + "data_points": [ + null, + { + "top_left_x": 10, + "top_left_y": 10, + "top_right_x": 10, + "top_right_y": 10, + "bottom_right_x": 20, + "bottom_right_y": 20, + "bottom_left_x": 20, + "bottom_left_y": 20 + }, + { + "top_left_x": 9.762664, + "top_left_y": 9.762664, + "top_right_x": 9.762664, + "top_right_y": 9.762664, + "bottom_right_x": 19.525328, + "bottom_right_y": 19.525328, + "bottom_left_x": 19.525328, + "bottom_left_y": 19.525328 + }, + { + "top_left_x": 8.969244, + "top_left_y": 8.969244, + "top_right_x": 8.969244, + "top_right_y": 8.969244, + "bottom_right_x": 17.938488, + "bottom_right_y": 17.938488, + "bottom_left_x": 17.938488, + "bottom_left_y": 17.938488 + }, + { + "top_left_x": 6.8709626, + "top_left_y": 6.8709626, + "top_right_x": 6.8709626, + "top_right_y": 6.8709626, + "bottom_right_x": 13.741925, + "bottom_right_y": 13.741925, + "bottom_left_x": 13.741925, + "bottom_left_y": 13.741925 + }, + { + "top_left_x": 3.260561, + "top_left_y": 3.260561, + "top_right_x": 3.260561, + "top_right_y": 3.260561, + "bottom_right_x": 6.521122, + "bottom_right_y": 6.521122, + "bottom_left_x": 6.521122, + "bottom_left_y": 6.521122 + }, + { + "top_left_x": 2.0915751, + "top_left_y": 2.0915751, + "top_right_x": 2.0915751, + "top_right_y": 2.0915751, + "bottom_right_x": 4.1831503, + "bottom_right_y": 4.1831503, + "bottom_left_x": 4.1831503, + "bottom_left_y": 4.1831503 + }, + { + "top_left_x": 1.4640827, + "top_left_y": 1.4640827, + "top_right_x": 1.4640827, + "top_right_y": 1.4640827, + "bottom_right_x": 2.9281654, + "bottom_right_y": 2.9281654, + "bottom_left_x": 2.9281654, + "bottom_left_y": 2.9281654 + }, + { + "top_left_x": 1.057313, + "top_left_y": 1.057313, + "top_right_x": 1.057313, + "top_right_y": 1.057313, + "bottom_right_x": 2.114626, + "bottom_right_y": 2.114626, + "bottom_left_x": 2.114626, + "bottom_left_y": 2.114626 + }, + { + "top_left_x": 0.7824335, + "top_left_y": 0.7824335, + "top_right_x": 0.7824335, + "top_right_y": 0.7824335, + "bottom_right_x": 1.564867, + "bottom_right_y": 1.564867, + "bottom_left_x": 1.564867, + "bottom_left_y": 1.564867 + }, + { + "top_left_x": 0.5863056, + "top_left_y": 0.5863056, + "top_right_x": 0.5863056, + "top_right_y": 0.5863056, + "bottom_right_x": 1.1726112, + "bottom_right_y": 1.1726112, + "bottom_left_x": 1.1726112, + "bottom_left_y": 1.1726112 + }, + { + "top_left_x": 0.4332962, + "top_left_y": 0.4332962, + "top_right_x": 0.4332962, + "top_right_y": 0.4332962, + "bottom_right_x": 0.8665924, + "bottom_right_y": 0.8665924, + "bottom_left_x": 0.8665924, + "bottom_left_y": 0.8665924 + }, + { + "top_left_x": 0.3145876, + "top_left_y": 0.3145876, + "top_right_x": 0.3145876, + "top_right_y": 0.3145876, + "bottom_right_x": 0.6291752, + "bottom_right_y": 0.6291752, + "bottom_left_x": 0.6291752, + "bottom_left_y": 0.6291752 + }, + { + "top_left_x": 0.22506618, + "top_left_y": 0.22506618, + "top_right_x": 0.22506618, + "top_right_y": 0.22506618, + "bottom_right_x": 0.45013237, + "bottom_right_y": 0.45013237, + "bottom_left_x": 0.45013237, + "bottom_left_y": 0.45013237 + }, + { + "top_left_x": 0.15591621, + "top_left_y": 0.15591621, + "top_right_x": 0.15591621, + "top_right_y": 0.15591621, + "bottom_right_x": 0.31183243, + "bottom_right_y": 0.31183243, + "bottom_left_x": 0.31183243, + "bottom_left_y": 0.31183243 + }, + { + "top_left_x": 0.100948334, + "top_left_y": 0.100948334, + "top_right_x": 0.100948334, + "top_right_y": 0.100948334, + "bottom_right_x": 0.20189667, + "bottom_right_y": 0.20189667, + "bottom_left_x": 0.20189667, + "bottom_left_y": 0.20189667 + }, + { + "top_left_x": 0.06496239, + "top_left_y": 0.06496239, + "top_right_x": 0.06496239, + "top_right_y": 0.06496239, + "bottom_right_x": 0.12992477, + "bottom_right_y": 0.12992477, + "bottom_left_x": 0.12992477, + "bottom_left_y": 0.12992477 + }, + { + "top_left_x": 0.03526497, + "top_left_y": 0.03526497, + "top_right_x": 0.03526497, + "top_right_y": 0.03526497, + "bottom_right_x": 0.07052994, + "bottom_right_y": 0.07052994, + "bottom_left_x": 0.07052994, + "bottom_left_y": 0.07052994 + }, + { + "top_left_x": 0.014661789, + "top_left_y": 0.014661789, + "top_right_x": 0.014661789, + "top_right_y": 0.014661789, + "bottom_right_x": 0.029323578, + "bottom_right_y": 0.029323578, + "bottom_left_x": 0.029323578, + "bottom_left_y": 0.029323578 + }, + { + "top_left_x": 0.0041856766, + "top_left_y": 0.0041856766, + "top_right_x": 0.0041856766, + "top_right_y": 0.0041856766, + "bottom_right_x": 0.008371353, + "bottom_right_y": 0.008371353, + "bottom_left_x": 0.008371353, + "bottom_left_y": 0.008371353 + }, + { + "top_left_x": 0, + "top_left_y": 0, + "top_right_x": 0, + "top_right_y": 0, + "bottom_right_x": 0, + "bottom_right_y": 0, + "bottom_left_x": 0, + "bottom_left_y": 0 + } + ] + }, + { + "name": "alpha", + "type": "int", + "data_points": [ + 0, + 0, + 115, + 178, + 217, + 241, + 253, + 239, + 183, + 135, + 91, + 53, + 23, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/goldens/backgroundAnimation_whenReturning.json b/packages/SystemUI/tests/goldens/backgroundAnimation_whenReturning.json new file mode 100644 index 000000000000..608e633d060b --- /dev/null +++ b/packages/SystemUI/tests/goldens/backgroundAnimation_whenReturning.json @@ -0,0 +1,393 @@ +{ + "frame_ids": [ + "before", + 0, + 26, + 52, + 78, + 105, + 131, + 157, + 184, + 210, + 236, + 263, + 289, + 315, + 342, + 368, + 394, + 421, + 447, + 473, + 500 + ], + "features": [ + { + "name": "bounds", + "type": "rect", + "data_points": [ + { + "left": 0, + "top": 0, + "right": 0, + "bottom": 0 + }, + { + "left": 100, + "top": 300, + "right": 200, + "bottom": 400 + }, + { + "left": 98, + "top": 293, + "right": 203, + "bottom": 407 + }, + { + "left": 91, + "top": 269, + "right": 213, + "bottom": 430 + }, + { + "left": 71, + "top": 206, + "right": 240, + "bottom": 491 + }, + { + "left": 34, + "top": 98, + "right": 283, + "bottom": 595 + }, + { + "left": 22, + "top": 63, + "right": 296, + "bottom": 629 + }, + { + "left": 15, + "top": 44, + "right": 303, + "bottom": 648 + }, + { + "left": 11, + "top": 32, + "right": 308, + "bottom": 659 + }, + { + "left": 8, + "top": 23, + "right": 311, + "bottom": 667 + }, + { + "left": 6, + "top": 18, + "right": 313, + "bottom": 673 + }, + { + "left": 5, + "top": 13, + "right": 315, + "bottom": 677 + }, + { + "left": 3, + "top": 9, + "right": 316, + "bottom": 681 + }, + { + "left": 2, + "top": 7, + "right": 317, + "bottom": 683 + }, + { + "left": 2, + "top": 5, + "right": 318, + "bottom": 685 + }, + { + "left": 1, + "top": 3, + "right": 319, + "bottom": 687 + }, + { + "left": 1, + "top": 2, + "right": 319, + "bottom": 688 + }, + { + "left": 0, + "top": 1, + "right": 320, + "bottom": 689 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + }, + { + "left": 0, + "top": 0, + "right": 320, + "bottom": 690 + } + ] + }, + { + "name": "corner_radii", + "type": "cornerRadii", + "data_points": [ + null, + { + "top_left_x": 10, + "top_left_y": 10, + "top_right_x": 10, + "top_right_y": 10, + "bottom_right_x": 20, + "bottom_right_y": 20, + "bottom_left_x": 20, + "bottom_left_y": 20 + }, + { + "top_left_x": 9.762664, + "top_left_y": 9.762664, + "top_right_x": 9.762664, + "top_right_y": 9.762664, + "bottom_right_x": 19.525328, + "bottom_right_y": 19.525328, + "bottom_left_x": 19.525328, + "bottom_left_y": 19.525328 + }, + { + "top_left_x": 8.969244, + "top_left_y": 8.969244, + "top_right_x": 8.969244, + "top_right_y": 8.969244, + "bottom_right_x": 17.938488, + "bottom_right_y": 17.938488, + "bottom_left_x": 17.938488, + "bottom_left_y": 17.938488 + }, + { + "top_left_x": 6.8709626, + "top_left_y": 6.8709626, + "top_right_x": 6.8709626, + "top_right_y": 6.8709626, + "bottom_right_x": 13.741925, + "bottom_right_y": 13.741925, + "bottom_left_x": 13.741925, + "bottom_left_y": 13.741925 + }, + { + "top_left_x": 3.260561, + "top_left_y": 3.260561, + "top_right_x": 3.260561, + "top_right_y": 3.260561, + "bottom_right_x": 6.521122, + "bottom_right_y": 6.521122, + "bottom_left_x": 6.521122, + "bottom_left_y": 6.521122 + }, + { + "top_left_x": 2.0915751, + "top_left_y": 2.0915751, + "top_right_x": 2.0915751, + "top_right_y": 2.0915751, + "bottom_right_x": 4.1831503, + "bottom_right_y": 4.1831503, + "bottom_left_x": 4.1831503, + "bottom_left_y": 4.1831503 + }, + { + "top_left_x": 1.4640827, + "top_left_y": 1.4640827, + "top_right_x": 1.4640827, + "top_right_y": 1.4640827, + "bottom_right_x": 2.9281654, + "bottom_right_y": 2.9281654, + "bottom_left_x": 2.9281654, + "bottom_left_y": 2.9281654 + }, + { + "top_left_x": 1.057313, + "top_left_y": 1.057313, + "top_right_x": 1.057313, + "top_right_y": 1.057313, + "bottom_right_x": 2.114626, + "bottom_right_y": 2.114626, + "bottom_left_x": 2.114626, + "bottom_left_y": 2.114626 + }, + { + "top_left_x": 0.7824335, + "top_left_y": 0.7824335, + "top_right_x": 0.7824335, + "top_right_y": 0.7824335, + "bottom_right_x": 1.564867, + "bottom_right_y": 1.564867, + "bottom_left_x": 1.564867, + "bottom_left_y": 1.564867 + }, + { + "top_left_x": 0.5863056, + "top_left_y": 0.5863056, + "top_right_x": 0.5863056, + "top_right_y": 0.5863056, + "bottom_right_x": 1.1726112, + "bottom_right_y": 1.1726112, + "bottom_left_x": 1.1726112, + "bottom_left_y": 1.1726112 + }, + { + "top_left_x": 0.4332962, + "top_left_y": 0.4332962, + "top_right_x": 0.4332962, + "top_right_y": 0.4332962, + "bottom_right_x": 0.8665924, + "bottom_right_y": 0.8665924, + "bottom_left_x": 0.8665924, + "bottom_left_y": 0.8665924 + }, + { + "top_left_x": 0.3145876, + "top_left_y": 0.3145876, + "top_right_x": 0.3145876, + "top_right_y": 0.3145876, + "bottom_right_x": 0.6291752, + "bottom_right_y": 0.6291752, + "bottom_left_x": 0.6291752, + "bottom_left_y": 0.6291752 + }, + { + "top_left_x": 0.22506618, + "top_left_y": 0.22506618, + "top_right_x": 0.22506618, + "top_right_y": 0.22506618, + "bottom_right_x": 0.45013237, + "bottom_right_y": 0.45013237, + "bottom_left_x": 0.45013237, + "bottom_left_y": 0.45013237 + }, + { + "top_left_x": 0.15591621, + "top_left_y": 0.15591621, + "top_right_x": 0.15591621, + "top_right_y": 0.15591621, + "bottom_right_x": 0.31183243, + "bottom_right_y": 0.31183243, + "bottom_left_x": 0.31183243, + "bottom_left_y": 0.31183243 + }, + { + "top_left_x": 0.100948334, + "top_left_y": 0.100948334, + "top_right_x": 0.100948334, + "top_right_y": 0.100948334, + "bottom_right_x": 0.20189667, + "bottom_right_y": 0.20189667, + "bottom_left_x": 0.20189667, + "bottom_left_y": 0.20189667 + }, + { + "top_left_x": 0.06496239, + "top_left_y": 0.06496239, + "top_right_x": 0.06496239, + "top_right_y": 0.06496239, + "bottom_right_x": 0.12992477, + "bottom_right_y": 0.12992477, + "bottom_left_x": 0.12992477, + "bottom_left_y": 0.12992477 + }, + { + "top_left_x": 0.03526497, + "top_left_y": 0.03526497, + "top_right_x": 0.03526497, + "top_right_y": 0.03526497, + "bottom_right_x": 0.07052994, + "bottom_right_y": 0.07052994, + "bottom_left_x": 0.07052994, + "bottom_left_y": 0.07052994 + }, + { + "top_left_x": 0.014661789, + "top_left_y": 0.014661789, + "top_right_x": 0.014661789, + "top_right_y": 0.014661789, + "bottom_right_x": 0.029323578, + "bottom_right_y": 0.029323578, + "bottom_left_x": 0.029323578, + "bottom_left_y": 0.029323578 + }, + { + "top_left_x": 0.0041856766, + "top_left_y": 0.0041856766, + "top_right_x": 0.0041856766, + "top_right_y": 0.0041856766, + "bottom_right_x": 0.008371353, + "bottom_right_y": 0.008371353, + "bottom_left_x": 0.008371353, + "bottom_left_y": 0.008371353 + }, + { + "top_left_x": 0, + "top_left_y": 0, + "top_right_x": 0, + "top_right_y": 0, + "bottom_right_x": 0, + "bottom_right_y": 0, + "bottom_left_x": 0, + "bottom_left_y": 0 + } + ] + }, + { + "name": "alpha", + "type": "int", + "data_points": [ + 0, + 0, + 115, + 178, + 217, + 241, + 253, + 239, + 183, + 135, + 91, + 53, + 23, + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt index 75a49d73cb59..41974f46ea7b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt @@ -246,6 +246,8 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { */ private class TestTransitionAnimatorController(override var transitionContainer: ViewGroup) : ActivityTransitionAnimator.Controller { + override val isLaunching: Boolean = true + override fun createAnimatorState() = TransitionAnimator.State( top = 100, diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt new file mode 100644 index 000000000000..c380a51f6a59 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TransitionAnimatorTest.kt @@ -0,0 +1,193 @@ +/* + * 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.systemui.animation + +import android.animation.AnimatorSet +import android.graphics.drawable.GradientDrawable +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.activity.EmptyTestActivity +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import platform.test.motion.RecordedMotion +import platform.test.motion.Sampling.Companion.evenlySampled +import platform.test.motion.view.DrawableFeatureCaptures +import platform.test.motion.view.ViewMotionTestRule +import platform.test.screenshot.DeviceEmulationRule +import platform.test.screenshot.DeviceEmulationSpec +import platform.test.screenshot.DisplaySpec +import platform.test.screenshot.GoldenPathManager +import platform.test.screenshot.PathConfig + +@SmallTest +@RunWith(AndroidJUnit4::class) +class TransitionAnimatorTest : SysuiTestCase() { + companion object { + private const val GOLDENS_PATH = "frameworks/base/packages/SystemUI/tests/goldens" + + private val emulationSpec = + DeviceEmulationSpec( + DisplaySpec( + "phone", + width = 320, + height = 690, + densityDpi = 160, + ) + ) + } + + private val pathManager = GoldenPathManager(context, GOLDENS_PATH, pathConfig = PathConfig()) + private val transitionAnimator = + TransitionAnimator( + ActivityTransitionAnimator.TIMINGS, + ActivityTransitionAnimator.INTERPOLATORS + ) + + @get:Rule(order = 0) val deviceEmulationRule = DeviceEmulationRule(emulationSpec) + @get:Rule(order = 1) val activityRule = ActivityScenarioRule(EmptyTestActivity::class.java) + @get:Rule(order = 2) + val motionRule = + ViewMotionTestRule<EmptyTestActivity>( + pathManager, + { activityRule.scenario }, + context = context, + bitmapDiffer = null, + ) + + @Test + fun backgroundAnimation_whenLaunching() { + val backgroundLayer = GradientDrawable().apply { alpha = 0 } + val animator = setUpTest(backgroundLayer, isLaunching = true) + + val recordedMotion = recordMotion(backgroundLayer, animator) + + motionRule.assertThat(recordedMotion).timeSeriesMatchesGolden() + } + + @Test + fun backgroundAnimation_whenReturning() { + val backgroundLayer = GradientDrawable().apply { alpha = 0 } + val animator = setUpTest(backgroundLayer, isLaunching = false) + + val recordedMotion = recordMotion(backgroundLayer, animator) + + motionRule.assertThat(recordedMotion).timeSeriesMatchesGolden() + } + + @Test + fun backgroundAnimationWithoutFade_whenLaunching() { + val backgroundLayer = GradientDrawable().apply { alpha = 0 } + val animator = + setUpTest(backgroundLayer, isLaunching = true, fadeWindowBackgroundLayer = false) + + val recordedMotion = recordMotion(backgroundLayer, animator) + + motionRule.assertThat(recordedMotion).timeSeriesMatchesGolden() + } + + @Test + fun backgroundAnimationWithoutFade_whenReturning() { + val backgroundLayer = GradientDrawable().apply { alpha = 0 } + val animator = + setUpTest(backgroundLayer, isLaunching = false, fadeWindowBackgroundLayer = false) + + val recordedMotion = recordMotion(backgroundLayer, animator) + + motionRule.assertThat(recordedMotion).timeSeriesMatchesGolden() + } + + private fun setUpTest( + backgroundLayer: GradientDrawable, + isLaunching: Boolean, + fadeWindowBackgroundLayer: Boolean = true, + ): AnimatorSet { + lateinit var transitionContainer: ViewGroup + activityRule.scenario.onActivity { activity -> + transitionContainer = FrameLayout(activity).apply { setBackgroundColor(0x00FF00) } + activity.setContentView(transitionContainer) + } + waitForIdleSync() + + val controller = TestController(transitionContainer, isLaunching) + val animator = + transitionAnimator.createAnimator( + controller, + createEndState(transitionContainer), + backgroundLayer, + fadeWindowBackgroundLayer + ) + return AnimatorSet().apply { + duration = animator.duration + play(animator) + } + } + + private fun createEndState(container: ViewGroup): TransitionAnimator.State { + val containerLocation = IntArray(2) + container.getLocationOnScreen(containerLocation) + return TransitionAnimator.State( + left = containerLocation[0], + top = containerLocation[1], + right = containerLocation[0] + emulationSpec.display.width, + bottom = containerLocation[1] + emulationSpec.display.height, + topCornerRadius = 0f, + bottomCornerRadius = 0f + ) + } + + private fun recordMotion( + backgroundLayer: GradientDrawable, + animator: AnimatorSet + ): RecordedMotion { + return motionRule.checkThat(animator).record( + backgroundLayer, + evenlySampled(20), + visualCapture = null + ) { + capture(DrawableFeatureCaptures.bounds, "bounds") + capture(DrawableFeatureCaptures.cornerRadii, "corner_radii") + capture(DrawableFeatureCaptures.alpha, "alpha") + } + } +} + +/** + * A simple implementation of [TransitionAnimator.Controller] which throws if it is called outside + * of the main thread. + */ +private class TestController( + override var transitionContainer: ViewGroup, + override val isLaunching: Boolean +) : TransitionAnimator.Controller { + override fun createAnimatorState(): TransitionAnimator.State { + val containerLocation = IntArray(2) + transitionContainer.getLocationOnScreen(containerLocation) + return TransitionAnimator.State( + left = containerLocation[0] + 100, + top = containerLocation[1] + 300, + right = containerLocation[0] + 200, + bottom = containerLocation[1] + 400, + topCornerRadius = 10f, + bottomCornerRadius = 20f + ) + } +} |