From 7bb867220fd86ca517b393030b61cfbc1dab3e36 Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Thu, 2 Jun 2022 15:02:38 +0200 Subject: [PATCH] Support Activity launches above the expandable This CL adds support for activity launches where the opening window is opening above the expandable surface. Before this CL, we would automatically assume that the opening window would be below the expandable surface, which is currently always the case given that the animator is used only in the shade and status bar at the moment (and those are above any app that we open). After this CL, the ActivityLaunchAnimator has an additional parameter for launches that happen above the expandable surface, which happen when launching an Activity from a normal app or from a launcher. Bug: 235576267 Test: Manual Change-Id: I49c6095ffe52119d117af6c597463542b4630bbd --- .../animation/ActivityLaunchAnimator.kt | 44 ++++++++++++++++--- .../systemui/animation/LaunchAnimator.kt | 18 +++++--- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index 02f8524a64f01..5b47ae5259190 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -332,6 +332,17 @@ class ActivityLaunchAnimator( val isDialogLaunch: Boolean get() = false + /** + * Whether the expandable controller by this [Controller] is below the launching window that + * is going to be animated. + * + * This should be `false` when launching an app from the shade or status bar, given that + * they are drawn above all apps. This is usually `true` when using this launcher in a + * normal app or a launcher, that are drawn below the animating activity/window. + */ + val isBelowAnimatingWindow: Boolean + get() = false + /** * The intent was started. If [willAnimate] is false, nothing else will happen and the * animation will not be started. @@ -468,7 +479,7 @@ class ActivityLaunchAnimator( // We animate the opening window and delegate the view expansion to [this.controller]. val delegate = this.controller val controller = - object : LaunchAnimator.Controller by delegate { + object : Controller by delegate { override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { listeners.forEach { it.onLaunchAnimationStart() } delegate.onLaunchAnimationStart(isExpandingFullyAbove) @@ -488,7 +499,7 @@ class ActivityLaunchAnimator( // Apply the state to the window only if it is visible, i.e. when the // expanding view is *not* visible. if (!state.visible) { - applyStateToWindow(window, state) + applyStateToWindow(window, state, linearProgress) } navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) } @@ -502,11 +513,16 @@ class ActivityLaunchAnimator( controller, endState, windowBackgroundColor, - drawHole = true + fadeOutWindowBackgroundLayer = !controller.isBelowAnimatingWindow, + drawHole = !controller.isBelowAnimatingWindow, ) } - private fun applyStateToWindow(window: RemoteAnimationTarget, state: LaunchAnimator.State) { + private fun applyStateToWindow( + window: RemoteAnimationTarget, + state: LaunchAnimator.State, + linearProgress: Float, + ) { if (transactionApplierView.viewRootImpl == null) { // If the view root we synchronize with was detached, don't apply any transaction // (as [SyncRtSurfaceTransactionApplier.scheduleApply] would otherwise throw). @@ -548,6 +564,24 @@ class ActivityLaunchAnimator( windowCropF.bottom.roundToInt() ) + // The alpha of the opening window. If it opens above the expandable, then it should + // fade in progressively. Otherwise, it should be fully opaque and will be progressively + // revealed as the window background color layer above the window fades out. + val alpha = + if (controller.isBelowAnimatingWindow) { + val windowProgress = + LaunchAnimator.getProgress( + TIMINGS, + linearProgress, + TIMINGS.contentAfterFadeInDelay, + TIMINGS.contentAfterFadeInDuration + ) + + INTERPOLATORS.contentAfterFadeInInterpolator.getInterpolation(windowProgress) + } else { + 1f + } + // The scale will also be applied to the corner radius, so we divide by the scale to // keep the original radius. We use the max of (topCornerRadius, bottomCornerRadius) to // make sure that the window does not draw itself behind the expanding view. This is @@ -556,7 +590,7 @@ class ActivityLaunchAnimator( val cornerRadius = maxOf(state.topCornerRadius, state.bottomCornerRadius) / scale val params = SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(window.leash) - .withAlpha(1f) + .withAlpha(alpha) .withMatrix(matrix) .withWindowCrop(windowCrop) .withCornerRadius(cornerRadius) diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt index 47a9802b7be85..9668066be1259 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt @@ -199,17 +199,19 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In /** * Start a launch animation controlled by [controller] towards [endState]. An intermediary layer - * with [windowBackgroundColor] will fade in then fade out above the expanding view, and should - * be the same background color as the opening (or closing) window. If [drawHole] is true, then - * this intermediary layer will be drawn with SRC blending mode while it fades out. + * 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. * - * TODO(b/184121838): Remove [drawHole] and instead make the StatusBar draw this hole instead. + * 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 [launch container][Controller.launchContainer]) iff [drawHole] is true. */ fun startAnimation( controller: Controller, endState: State, windowBackgroundColor: Int, - drawHole: Boolean = false + fadeOutWindowBackgroundLayer: Boolean = true, + drawHole: Boolean = false, ): Animation { val state = controller.createAnimatorState() @@ -369,6 +371,7 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In state, linearProgress, container, + fadeOutWindowBackgroundLayer, drawHole ) controller.onLaunchAnimationProgress(state, progress, linearProgress) @@ -397,6 +400,7 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In state: State, linearProgress: Float, launchContainer: View, + fadeOutWindowBackgroundLayer: Boolean, drawHole: Boolean ) { // Update position. @@ -432,7 +436,7 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In val alpha = interpolators.contentBeforeFadeOutInterpolator.getInterpolation(fadeInProgress) drawable.alpha = (alpha * 0xFF).roundToInt() - } else { + } else if (fadeOutWindowBackgroundLayer) { val fadeOutProgress = getProgress( timings, @@ -447,6 +451,8 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In if (drawHole) { drawable.setXfermode(SRC_MODE) } + } else { + drawable.alpha = 0xFF } } }