Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4e38a94 authored by Luca Zuccarini's avatar Luca Zuccarini
Browse files

Rename LaunchAnimator to cover transitions in general.

Soon it will be used for both launches and returns, so this name is
more accurate.

Bug: 323863002
Flag: NA
Test: still builds (no functionality change)
Change-Id: Icc5bcb5ed9df63a620c51a430063d5246b1e3ae5
parent 3c8e0f44
Loading
Loading
Loading
Loading
+40 −39
Original line number Diff line number Diff line
@@ -53,12 +53,12 @@ private const val TAG = "ActivityLaunchAnimator"
 */
class ActivityLaunchAnimator(
    /** The animator used when animating a View into an app. */
    private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR,
    private val transitionAnimator: TransitionAnimator = DEFAULT_TRANSITION_ANIMATOR,

    /** The animator used when animating a Dialog into an app. */
    // TODO(b/218989950): Remove this animator and instead set the duration of the dim fade out to
    // TIMINGS.contentBeforeFadeOutDuration.
    private val dialogToAppAnimator: LaunchAnimator = DEFAULT_DIALOG_TO_APP_ANIMATOR,
    private val dialogToAppAnimator: TransitionAnimator = DEFAULT_DIALOG_TO_APP_ANIMATOR,

    /**
     * Whether we should disable the WindowManager timeout. This should be set to true in tests
@@ -71,7 +71,7 @@ class ActivityLaunchAnimator(
        /** The timings when animating a View into an app. */
        @JvmField
        val TIMINGS =
            LaunchAnimator.Timings(
            TransitionAnimator.Timings(
                totalDuration = 500L,
                contentBeforeFadeOutDelay = 0L,
                contentBeforeFadeOutDuration = 150L,
@@ -89,7 +89,7 @@ class ActivityLaunchAnimator(

        /** The interpolators when animating a View or a dialog into an app. */
        val INTERPOLATORS =
            LaunchAnimator.Interpolators(
            TransitionAnimator.Interpolators(
                positionInterpolator = Interpolators.EMPHASIZED,
                positionXInterpolator = Interpolators.EMPHASIZED_COMPLEMENT,
                contentBeforeFadeOutInterpolator = Interpolators.LINEAR_OUT_SLOW_IN,
@@ -99,8 +99,9 @@ class ActivityLaunchAnimator(
        // TODO(b/288507023): Remove this flag.
        @JvmField val DEBUG_LAUNCH_ANIMATION = Build.IS_DEBUGGABLE

        private val DEFAULT_LAUNCH_ANIMATOR = LaunchAnimator(TIMINGS, INTERPOLATORS)
        private val DEFAULT_DIALOG_TO_APP_ANIMATOR = LaunchAnimator(DIALOG_TIMINGS, INTERPOLATORS)
        private val DEFAULT_TRANSITION_ANIMATOR = TransitionAnimator(TIMINGS, INTERPOLATORS)
        private val DEFAULT_DIALOG_TO_APP_ANIMATOR =
            TransitionAnimator(DIALOG_TIMINGS, INTERPOLATORS)

        /** Durations & interpolators for the navigation bar fading in & out. */
        private const val ANIMATION_DURATION_NAV_FADE_IN = 266L
@@ -154,7 +155,7 @@ class ActivityLaunchAnimator(
     * Start an intent and animate the opening window. The intent will be started by running
     * [intentStarter], which should use the provided [RemoteAnimationAdapter] and return the launch
     * result. [controller] is responsible from animating the view from which the intent was started
     * in [Controller.onLaunchAnimationProgress]. No animation will start if there is no window
     * in [Controller.onTransitionAnimationProgress]. No animation will start if there is no window
     * opening.
     *
     * If [controller] is null or [animate] is false, then the intent will be started and no
@@ -255,7 +256,7 @@ class ActivityLaunchAnimator(

    private fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            this.launchContainer.context.mainExecutor.execute {
            this.transitionContainer.context.mainExecutor.execute {
                callOnIntentStartedOnMainThread(willAnimate)
            }
        } else {
@@ -306,14 +307,14 @@ class ActivityLaunchAnimator(
    @VisibleForTesting
    fun createRunner(controller: Controller): Runner {
        // Make sure we use the modified timings when animating a dialog into an app.
        val launchAnimator =
        val transitionAnimator =
            if (controller.isDialogLaunch) {
                dialogToAppAnimator
            } else {
                launchAnimator
                transitionAnimator
            }

        return Runner(controller, callback!!, launchAnimator, lifecycleListener)
        return Runner(controller, callback!!, transitionAnimator, lifecycleListener)
    }

    interface PendingIntentStarter {
@@ -364,7 +365,7 @@ class ActivityLaunchAnimator(
     *
     * Note that all callbacks (onXXX methods) are all called on the main thread.
     */
    interface Controller : LaunchAnimator.Controller {
    interface Controller : TransitionAnimator.Controller {
        companion object {
            /**
             * Return a [Controller] that will animate and expand [view] into the opening window.
@@ -427,9 +428,9 @@ class ActivityLaunchAnimator(
        fun onIntentStarted(willAnimate: Boolean) {}

        /**
         * The animation was cancelled. Note that [onLaunchAnimationEnd] will still be called after
         * this if the animation was already started, i.e. if [onLaunchAnimationStart] was called
         * before the cancellation.
         * The animation was cancelled. Note that [onTransitionAnimationEnd] will still be called
         * after this if the animation was already started, i.e. if [onTransitionAnimationStart] was
         * called before the cancellation.
         *
         * If this launch animation affected the occlusion state of the keyguard, WM will provide us
         * with [newKeyguardOccludedState] so that we can set the occluded state appropriately.
@@ -475,11 +476,11 @@ class ActivityLaunchAnimator(
        controller: Controller,
        callback: Callback,
        /** The animator to use to animate the window launch. */
        launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR,
        transitionAnimator: TransitionAnimator = DEFAULT_TRANSITION_ANIMATOR,
        /** Listener for animation lifecycle events. */
        listener: Listener? = null
    ) : IRemoteAnimationRunner.Stub() {
        private val context = controller.launchContainer.context
        private val context = controller.transitionContainer.context

        // This is being passed across IPC boundaries and cycles (through PendingIntentRecords,
        // etc.) are possible. So we need to make sure we drop any references that might
@@ -492,7 +493,7 @@ class ActivityLaunchAnimator(
                    controller,
                    callback,
                    DelegatingAnimationCompletionListener(listener, this::dispose),
                    launchAnimator,
                    transitionAnimator,
                    disableWmTimeout
                )
        }
@@ -543,7 +544,7 @@ class ActivityLaunchAnimator(
        /** Listener for animation lifecycle events. */
        private val listener: Listener? = null,
        /** The animator to use to animate the window launch. */
        private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR,
        private val transitionAnimator: TransitionAnimator = DEFAULT_TRANSITION_ANIMATOR,

        /**
         * Whether we should disable the WindowManager timeout. This should be set to true in tests
@@ -552,10 +553,10 @@ class ActivityLaunchAnimator(
        // TODO(b/301385865): Remove this flag.
        disableWmTimeout: Boolean = false,
    ) : RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> {
        private val launchContainer = controller.launchContainer
        private val context = launchContainer.context
        private val transitionContainer = controller.transitionContainer
        private val context = transitionContainer.context
        private val transactionApplierView =
            controller.openingWindowSyncView ?: controller.launchContainer
            controller.openingWindowSyncView ?: controller.transitionContainer
        private val transactionApplier = SyncRtSurfaceTransactionApplier(transactionApplierView)
        private val timeoutHandler =
            if (!disableWmTimeout) {
@@ -570,7 +571,7 @@ class ActivityLaunchAnimator(
        private var windowCropF = RectF()
        private var timedOut = false
        private var cancelled = false
        private var animation: LaunchAnimator.Animation? = null
        private var animation: TransitionAnimator.Animation? = null

        /**
         * A timeout to cancel the launch animation if the remote animation is not started or
@@ -660,7 +661,7 @@ class ActivityLaunchAnimator(
            nonApps: Array<out RemoteAnimationTarget>?,
            iCallback: IRemoteAnimationFinishedCallback?
        ) {
            if (LaunchAnimator.DEBUG) {
            if (TransitionAnimator.DEBUG) {
                Log.d(TAG, "Remote animation started")
            }

@@ -687,7 +688,7 @@ class ActivityLaunchAnimator(

            val windowBounds = window.screenSpaceBounds
            val endState =
                LaunchAnimator.State(
                TransitionAnimator.State(
                    top = windowBounds.top,
                    bottom = windowBounds.bottom,
                    left = windowBounds.left,
@@ -699,7 +700,7 @@ class ActivityLaunchAnimator(
            // TODO(b/184121838): We should somehow get the top and bottom radius of the window
            // instead of recomputing isExpandingFullyAbove here.
            val isExpandingFullyAbove =
                launchAnimator.isExpandingFullyAbove(controller.launchContainer, endState)
                transitionAnimator.isExpandingFullyAbove(controller.transitionContainer, endState)
            val endRadius =
                if (isExpandingFullyAbove) {
                    // Most of the time, expanding fully above the root view means expanding in full
@@ -718,7 +719,7 @@ class ActivityLaunchAnimator(
            val delegate = this.controller
            val controller =
                object : Controller by delegate {
                    override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
                    override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
                        listener?.onLaunchAnimationStart()

                        if (DEBUG_LAUNCH_ANIMATION) {
@@ -728,10 +729,10 @@ class ActivityLaunchAnimator(
                                    "$isExpandingFullyAbove) [controller=$delegate]"
                            )
                        }
                        delegate.onLaunchAnimationStart(isExpandingFullyAbove)
                        delegate.onTransitionAnimationStart(isExpandingFullyAbove)
                    }

                    override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
                    override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
                        listener?.onLaunchAnimationEnd()
                        iCallback?.invoke()

@@ -742,11 +743,11 @@ class ActivityLaunchAnimator(
                                    "$isExpandingFullyAbove) [controller=$delegate]"
                            )
                        }
                        delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
                        delegate.onTransitionAnimationEnd(isExpandingFullyAbove)
                    }

                    override fun onLaunchAnimationProgress(
                        state: LaunchAnimator.State,
                    override fun onTransitionAnimationProgress(
                        state: TransitionAnimator.State,
                        progress: Float,
                        linearProgress: Float
                    ) {
@@ -758,12 +759,12 @@ class ActivityLaunchAnimator(
                        navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) }

                        listener?.onLaunchAnimationProgress(linearProgress)
                        delegate.onLaunchAnimationProgress(state, progress, linearProgress)
                        delegate.onTransitionAnimationProgress(state, progress, linearProgress)
                    }
                }

            animation =
                launchAnimator.startAnimation(
                transitionAnimator.startAnimation(
                    controller,
                    endState,
                    windowBackgroundColor,
@@ -774,7 +775,7 @@ class ActivityLaunchAnimator(

        private fun applyStateToWindow(
            window: RemoteAnimationTarget,
            state: LaunchAnimator.State,
            state: TransitionAnimator.State,
            linearProgress: Float,
        ) {
            if (transactionApplierView.viewRootImpl == null || !window.leash.isValid) {
@@ -825,7 +826,7 @@ class ActivityLaunchAnimator(
            val alpha =
                if (controller.isBelowAnimatingWindow) {
                    val windowProgress =
                        LaunchAnimator.getProgress(
                        TransitionAnimator.getProgress(
                            TIMINGS,
                            linearProgress,
                            TIMINGS.contentAfterFadeInDelay,
@@ -857,7 +858,7 @@ class ActivityLaunchAnimator(

        private fun applyStateToNavigationBar(
            navigationBar: RemoteAnimationTarget,
            state: LaunchAnimator.State,
            state: TransitionAnimator.State,
            linearProgress: Float
        ) {
            if (transactionApplierView.viewRootImpl == null || !navigationBar.leash.isValid) {
@@ -868,7 +869,7 @@ class ActivityLaunchAnimator(
            }

            val fadeInProgress =
                LaunchAnimator.getProgress(
                TransitionAnimator.getProgress(
                    TIMINGS,
                    linearProgress,
                    ANIMATION_DELAY_NAV_FADE_IN,
@@ -890,7 +891,7 @@ class ActivityLaunchAnimator(
                    .withVisibility(true)
            } else {
                val fadeOutProgress =
                    LaunchAnimator.getProgress(
                    TransitionAnimator.getProgress(
                        TIMINGS,
                        linearProgress,
                        0,
+31 −31
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ constructor(
    private val callback: Callback,
    private val interactionJankMonitor: InteractionJankMonitor,
    private val featureFlags: AnimationFeatureFlags,
    private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
    private val transitionAnimator: TransitionAnimator = TransitionAnimator(TIMINGS, INTERPOLATORS),
    private val isForTesting: Boolean = false,
) {
    private companion object {
@@ -108,21 +108,21 @@ constructor(
        fun stopDrawingInOverlay()

        /**
         * Create the [LaunchAnimator.Controller] that will be called to animate the source
         * Create the [TransitionAnimator.Controller] that will be called to animate the source
         * controlled by this [Controller] during the dialog launch animation.
         *
         * At the end of this animation, the source should *not* be visible anymore (until the
         * dialog is closed and is animated back into the source).
         */
        fun createLaunchController(): LaunchAnimator.Controller
        fun createTransitionController(): TransitionAnimator.Controller

        /**
         * Create the [LaunchAnimator.Controller] that will be called to animate the source
         * Create the [TransitionAnimator.Controller] that will be called to animate the source
         * controlled by this [Controller] during the dialog exit animation.
         *
         * At the end of this animation, the source should be visible again.
         */
        fun createExitController(): LaunchAnimator.Controller
        fun createExitController(): TransitionAnimator.Controller

        /**
         * Whether we should animate the dialog back into the source when it is dismissed. If this
@@ -270,7 +270,7 @@ constructor(

        val animatedDialog =
            AnimatedDialog(
                launchAnimator = launchAnimator,
                transitionAnimator = transitionAnimator,
                callback = callback,
                interactionJankMonitor = interactionJankMonitor,
                controller = controller,
@@ -406,8 +406,8 @@ constructor(
                dialog.dismiss()
            }

            override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
                controller.onLaunchAnimationStart(isExpandingFullyAbove)
            override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
                controller.onTransitionAnimationStart(isExpandingFullyAbove)

                // Make sure the dialog is not dismissed during the animation.
                disableDialogDismiss()
@@ -420,8 +420,8 @@ constructor(
                dialog.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
            }

            override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
                controller.onLaunchAnimationEnd(isExpandingFullyAbove)
            override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
                controller.onTransitionAnimationEnd(isExpandingFullyAbove)

                // Hide the dialog then dismiss it to instantly dismiss it without playing the
                // animation.
@@ -492,7 +492,7 @@ constructor(
data class DialogCuj(@CujType val cujType: Int, val tag: String? = null)

private class AnimatedDialog(
    private val launchAnimator: LaunchAnimator,
    private val transitionAnimator: TransitionAnimator,
    private val callback: DialogLaunchAnimator.Callback,
    private val interactionJankMonitor: InteractionJankMonitor,

@@ -892,7 +892,7 @@ private class AnimatedDialog(
        // Create 2 controllers to animate both the dialog and the source.
        val startController =
            if (isLaunching) {
                controller.createLaunchController()
                controller.createTransitionController()
            } else {
                GhostedViewLaunchAnimatorController(dialogContentWithBackground!!)
            }
@@ -902,34 +902,34 @@ private class AnimatedDialog(
            } else {
                controller.createExitController()
            }
        startController.launchContainer = decorView
        endController.launchContainer = decorView
        startController.transitionContainer = decorView
        endController.transitionContainer = decorView

        val endState = endController.createAnimatorState()
        val controller =
            object : LaunchAnimator.Controller {
                override var launchContainer: ViewGroup
                    get() = startController.launchContainer
            object : TransitionAnimator.Controller {
                override var transitionContainer: ViewGroup
                    get() = startController.transitionContainer
                    set(value) {
                        startController.launchContainer = value
                        endController.launchContainer = value
                        startController.transitionContainer = value
                        endController.transitionContainer = value
                    }

                override fun createAnimatorState(): LaunchAnimator.State {
                override fun createAnimatorState(): TransitionAnimator.State {
                    return startController.createAnimatorState()
                }

                override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
                override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
                    // During launch, onLaunchAnimationStart will be used to remove the temporary
                    // touch surface ghost so it is important to call this before calling
                    // onLaunchAnimationStart on the controller (which will create its own ghost).
                    onLaunchAnimationStart()

                    startController.onLaunchAnimationStart(isExpandingFullyAbove)
                    endController.onLaunchAnimationStart(isExpandingFullyAbove)
                    startController.onTransitionAnimationStart(isExpandingFullyAbove)
                    endController.onTransitionAnimationStart(isExpandingFullyAbove)
                }

                override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
                override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
                    // onLaunchAnimationEnd is called by an Animator at the end of the animation,
                    // on a Choreographer animation tick. The following calls will move the animated
                    // content from the dialog overlay back to its original position, and this
@@ -943,23 +943,23 @@ private class AnimatedDialog(
                    // that the move of the content back to its original window will be reflected in
                    // the next frame right after [onLaunchAnimationEnd] is called.
                    dialog.context.mainExecutor.execute {
                        startController.onLaunchAnimationEnd(isExpandingFullyAbove)
                        endController.onLaunchAnimationEnd(isExpandingFullyAbove)
                        startController.onTransitionAnimationEnd(isExpandingFullyAbove)
                        endController.onTransitionAnimationEnd(isExpandingFullyAbove)

                        onLaunchAnimationEnd()
                    }
                }

                override fun onLaunchAnimationProgress(
                    state: LaunchAnimator.State,
                override fun onTransitionAnimationProgress(
                    state: TransitionAnimator.State,
                    progress: Float,
                    linearProgress: Float
                ) {
                    startController.onLaunchAnimationProgress(state, progress, linearProgress)
                    startController.onTransitionAnimationProgress(state, progress, linearProgress)

                    // The end view is visible only iff the starting view is not visible.
                    state.visible = !state.visible
                    endController.onLaunchAnimationProgress(state, progress, linearProgress)
                    endController.onTransitionAnimationProgress(state, progress, linearProgress)

                    // If the dialog content is complex, its dimension might change during the
                    // launch animation. The animation end position might also change during the
@@ -973,7 +973,7 @@ private class AnimatedDialog(
                }
            }

        launchAnimator.startAnimation(controller, endState, originalDialogBackgroundColor)
        transitionAnimator.startAnimation(controller, endState, originalDialogBackgroundColor)
    }

    private fun shouldAnimateDialogIntoSource(): Boolean {
+25 −25

File changed.

Preview size limit exceeded, changes collapsed.

+54 −49

File changed and moved.

Preview size limit exceeded, changes collapsed.

+7 −7
Original line number Diff line number Diff line
@@ -68,19 +68,19 @@ internal constructor(
        }
    }

    override fun createLaunchController(): LaunchAnimator.Controller {
    override fun createTransitionController(): TransitionAnimator.Controller {
        val delegate = GhostedViewLaunchAnimatorController(source)
        return object : LaunchAnimator.Controller by delegate {
            override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
        return object : TransitionAnimator.Controller by delegate {
            override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
                // Remove the temporary ghost added by [startDrawingInOverlayOf]. Another
                // ghost (that ghosts only the source content, and not its background) will
                // be added right after this by the delegate and will be animated.
                GhostView.removeGhost(source)
                delegate.onLaunchAnimationStart(isExpandingFullyAbove)
                delegate.onTransitionAnimationStart(isExpandingFullyAbove)
            }

            override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
                delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
            override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) {
                delegate.onTransitionAnimationEnd(isExpandingFullyAbove)

                // At this point the view visibility is restored by the delegate, so we delay the
                // visibility changes again and make it invisible while the dialog is shown.
@@ -94,7 +94,7 @@ internal constructor(
        }
    }

    override fun createExitController(): LaunchAnimator.Controller {
    override fun createExitController(): TransitionAnimator.Controller {
        return GhostedViewLaunchAnimatorController(source)
    }

Loading