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

Commit 5c6fd9b6 authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Desktop-Minimize: move CUJ handling to MinimizeAnimator

- Move CUJ handling for the Desktop window minimize animation from
DesktopTasksLimiter to MinimizeAnimator.
- Also add ShellAnimationThread Handler to be able to pass such a Handler
to InteractionJankMonitor for the minimize-window animation in
FreeformTaskTransitionHandler.

Flag: NONE jank/logging only change
Test: manual (perfetto)
Bug: 374206096
Bug: 385051575
Change-Id: Id2bb7fa223ebdafb301c853941282f9c8a533b57
parent e2e8e87f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -73,6 +73,12 @@ public class Interpolators {
    public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
            0.05f, 0.7f, 0.1f, 1f);

    /**
     * The standard accelerating interpolator that should be used on every regular movement of
     * content that is disappearing e.g. when moving off screen.
     */
    public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(0.3f, 0f, 1f, 1f);

    /**
     * The standard decelerating interpolator that should be used on every regular movement of
     * content that is appearing e.g. when coming from off screen.
+37 −13
Original line number Diff line number Diff line
@@ -19,52 +19,76 @@ package com.android.wm.shell.shared.animation
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.util.DisplayMetrics
import android.content.Context
import android.os.Handler
import android.view.Choreographer
import android.view.SurfaceControl.Transaction
import android.view.animation.LinearInterpolator
import android.view.animation.PathInterpolator
import android.window.TransitionInfo.Change
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW
import com.android.internal.jank.InteractionJankMonitor

/** Creates minimization animation */
object MinimizeAnimator {

    private const val MINIMIZE_ANIM_ALPHA_DURATION_MS = 100L

    private val STANDARD_ACCELERATE = PathInterpolator(0.3f, 0f, 1f, 1f)

    private val minimizeBoundsAnimationDef =
        WindowAnimator.BoundsAnimationParams(
            durationMs = 200,
            endOffsetYDp = 12f,
            endScale = 0.97f,
            interpolator = STANDARD_ACCELERATE,
            interpolator = Interpolators.STANDARD_ACCELERATE,
        )

    /**
     * Creates a minimize animator for given task [Change].
     *
     * @param onAnimFinish finish-callback for the animation, note that this is called on the same
     * thread as the animation itself.
     * @param animationHandler the Handler that the animation is running on.
     */
    @JvmStatic
    fun create(
        displayMetrics: DisplayMetrics,
        context: Context,
        change: Change,
        transaction: Transaction,
        onAnimFinish: (Animator) -> Unit,
        interactionJankMonitor: InteractionJankMonitor,
        animationHandler: Handler,
    ): Animator {
        val boundsAnimator = WindowAnimator.createBoundsAnimator(
            displayMetrics,
            context.resources.displayMetrics,
            minimizeBoundsAnimationDef,
            change,
            transaction,
        )
        val alphaAnimator = ValueAnimator.ofFloat(1f, 0f).apply {
            duration = MINIMIZE_ANIM_ALPHA_DURATION_MS
            interpolator = LinearInterpolator()
            interpolator = Interpolators.LINEAR
            addUpdateListener { animation ->
                transaction.setAlpha(change.leash, animation.animatedValue as Float).apply()
                transaction
                    .setAlpha(change.leash, animation.animatedValue as Float)
                    .setFrameTimeline(Choreographer.getInstance().vsyncId)
                    .apply()
            }
        }
        val listener = object : Animator.AnimatorListener {
            override fun onAnimationEnd(animator: Animator) = onAnimFinish(animator)
            override fun onAnimationCancel(animator: Animator) = Unit
            override fun onAnimationStart(animator: Animator) {
                interactionJankMonitor.begin(
                    change.leash,
                    context,
                    animationHandler,
                    CUJ_DESKTOP_MODE_MINIMIZE_WINDOW,
                )
            }
            override fun onAnimationCancel(animator: Animator) {
                interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
            }
            override fun onAnimationRepeat(animator: Animator) = Unit
            override fun onAnimationStart(animator: Animator) = Unit
            override fun onAnimationEnd(animator: Animator) {
                interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)
                onAnimFinish(animator)
            }
        }
        return AnimatorSet().apply {
            playTogether(boundsAnimator, alphaAnimator)
+19 −10
Original line number Diff line number Diff line
@@ -162,22 +162,31 @@ public abstract class WMShellConcurrencyModule {
        }
    }

    /**
     * Provide a Shell animation-thread Executor.
     */
    /** Provide a Shell animation-thread Handler. */
    @WMSingleton
    @Provides
    @ShellAnimationThread
    public static ShellExecutor provideShellAnimationExecutor() {
         HandlerThread shellAnimationThread = new HandlerThread("wmshell.anim",
                 THREAD_PRIORITY_DISPLAY);
         shellAnimationThread.start();
    public static Handler provideShellAnimationHandler() {
        HandlerThread animThread = new HandlerThread("wmshell.anim", THREAD_PRIORITY_DISPLAY);
        animThread.start();
        if (Build.IS_DEBUGGABLE) {
            shellAnimationThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
            shellAnimationThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
            animThread.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
            animThread.getLooper().setSlowLogThresholdMs(MSGQ_SLOW_DISPATCH_THRESHOLD_MS,
                    MSGQ_SLOW_DELIVERY_THRESHOLD_MS);
        }
         return new HandlerExecutor(Handler.createAsync(shellAnimationThread.getLooper()));
        return Handler.createAsync(animThread.getLooper());
    }

    /**
     * Provide a Shell animation-thread Executor.
     */
    @WMSingleton
    @Provides
    @ShellAnimationThread
    public static ShellExecutor provideShellAnimationExecutor(
            @ShellAnimationThread Handler animHandler
    ) {
        return new HandlerExecutor(animHandler);
    }

    /**
+6 −4
Original line number Diff line number Diff line
@@ -428,9 +428,10 @@ public abstract class WMShellModule {
            Transitions transitions,
            DisplayController displayController,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellAnimationThread ShellExecutor animExecutor) {
            @ShellAnimationThread ShellExecutor animExecutor,
            @ShellAnimationThread Handler animHandler) {
        return new FreeformTaskTransitionHandler(
                transitions, displayController, mainExecutor, animExecutor);
                transitions, displayController, mainExecutor, animExecutor, animHandler);
    }

    @WMSingleton
@@ -1083,9 +1084,10 @@ public abstract class WMShellModule {
    static DesktopMinimizationTransitionHandler provideDesktopMinimizationTransitionHandler(
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellAnimationThread ShellExecutor animExecutor,
            DisplayController displayController) {
            DisplayController displayController,
            @ShellAnimationThread Handler mainHandler) {
        return new DesktopMinimizationTransitionHandler(mainExecutor, animExecutor,
                displayController);
                displayController, mainHandler);
    }

    @WMSingleton
+30 −6
Original line number Diff line number Diff line
@@ -18,14 +18,17 @@ package com.android.wm.shell.desktopmode

import android.animation.Animator
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.os.Handler
import android.os.IBinder
import android.util.DisplayMetrics
import android.view.SurfaceControl.Transaction
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.animation.MinimizeAnimator.create
import com.android.wm.shell.transition.Transitions
@@ -41,6 +44,7 @@ class DesktopMinimizationTransitionHandler(
    private val mainExecutor: ShellExecutor,
    private val animExecutor: ShellExecutor,
    private val displayController: DisplayController,
    private val animHandler: Handler,
) : Transitions.TransitionHandler {

    /** Shouldn't handle anything */
@@ -90,10 +94,30 @@ class DesktopMinimizationTransitionHandler(
        val t = Transaction()
        val sc = change.leash
        finishTransaction.hide(sc)
        val displayMetrics: DisplayMetrics? =
            change.taskInfo?.let {
                displayController.getDisplayContext(it.displayId)?.getResources()?.displayMetrics
        val displayContext =
            change.taskInfo?.let { displayController.getDisplayContext(it.displayId) }
        if (displayContext == null) {
            logW(
                "displayContext is null for taskId=${change.taskInfo?.taskId}, " +
                    "displayId=${change.taskInfo?.displayId}"
            )
            return null
        }
        return displayMetrics?.let { create(it, change, t, onAnimFinish) }
        return create(
            displayContext,
            change,
            t,
            onAnimFinish,
            InteractionJankMonitor.getInstance(),
            animHandler,
        )
    }

    private companion object {
        private fun logW(msg: String, vararg arguments: Any?) {
            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
        }

        const val TAG = "DesktopMinimizationTransitionHandler"
    }
}
Loading