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 } } }