Loading core/java/com/android/internal/jank/Cuj.java +15 −2 Original line number Diff line number Diff line Loading @@ -265,8 +265,17 @@ public class Cuj { */ public static final int CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS = 121; /** * Track closing task in Desktop Windowing. * * <p> Tracking begins when the CloseDesktopTaskTransitionHandler in Launcher starts * animating the task closure. This is triggered when the close button in the app header is * clicked on a desktop window. </p> */ public static final int CUJ_DESKTOP_MODE_CLOSE_TASK = 122; // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. @VisibleForTesting static final int LAST_CUJ = CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS; @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_CLOSE_TASK; /** @hide */ @IntDef({ Loading Loading @@ -379,7 +388,8 @@ public class Cuj { CUJ_DESKTOP_MODE_SNAP_RESIZE, CUJ_DESKTOP_MODE_UNMAXIMIZE_WINDOW, CUJ_DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU, CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS, CUJ_DESKTOP_MODE_CLOSE_TASK }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} Loading Loading @@ -503,6 +513,7 @@ public class Cuj { CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_UNMAXIMIZE_WINDOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_UNMAXIMIZE_WINDOW; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OVERVIEW_TASK_DISMISS; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_CLOSE_TASK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_CLOSE_TASK; } private Cuj() { Loading Loading @@ -741,6 +752,8 @@ public class Cuj { return "DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU"; case CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS: return "LAUNCHER_OVERVIEW_TASK_DISMISS"; case CUJ_DESKTOP_MODE_CLOSE_TASK: return "DESKTOP_MODE_CLOSE_TASK"; } return "UNKNOWN"; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −2 Original line number Diff line number Diff line Loading @@ -1031,8 +1031,9 @@ public abstract class WMShellModule { static CloseDesktopTaskTransitionHandler provideCloseDesktopTaskTransitionHandler( Context context, @ShellMainThread ShellExecutor mainExecutor, @ShellAnimationThread ShellExecutor animExecutor) { return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor); @ShellAnimationThread ShellExecutor animExecutor, @ShellMainThread Handler handler) { return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor, handler); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandler.kt +23 −6 Original line number Diff line number Diff line Loading @@ -23,8 +23,10 @@ import android.animation.ValueAnimator import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.content.Context import android.graphics.Rect import android.os.Handler import android.os.IBinder import android.util.TypedValue import android.view.Choreographer import android.view.SurfaceControl.Transaction import android.view.WindowManager import android.window.TransitionInfo Loading @@ -32,7 +34,10 @@ import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import androidx.core.animation.addListener import com.android.app.animation.Interpolators import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_CLOSE_TASK import com.android.internal.jank.InteractionJankMonitor import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.Transitions import java.util.function.Supplier Loading @@ -44,9 +49,11 @@ constructor( private val mainExecutor: ShellExecutor, private val animExecutor: ShellExecutor, private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() }, @ShellMainThread private val handler: Handler, ) : Transitions.TransitionHandler { private val runningAnimations = mutableMapOf<IBinder, List<Animator>>() private val interactionJankMonitor = InteractionJankMonitor.getInstance() /** Returns null, as it only handles transitions started from Shell. */ override fun handleRequest( Loading @@ -71,18 +78,27 @@ constructor( // All animations completed, finish the transition runningAnimations.remove(transition) finishCallback.onTransitionFinished(/* wct= */ null) interactionJankMonitor.end(CUJ_DESKTOP_MODE_CLOSE_TASK) } } } animations += info.changes .filter { val closingChanges = info.changes.filter { it.mode == WindowManager.TRANSIT_CLOSE && it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM } .map { createCloseAnimation(it, finishTransaction, onAnimFinish) } animations += closingChanges.map { createCloseAnimation(it, finishTransaction, onAnimFinish) } if (animations.isEmpty()) return false runningAnimations[transition] = animations closingChanges.lastOrNull()?.leash?.let { lastChangeLeash -> interactionJankMonitor.begin( lastChangeLeash, context, handler, CUJ_DESKTOP_MODE_CLOSE_TASK, ) } animExecutor.execute { animations.forEach(Animator::start) } return true } Loading Loading @@ -127,6 +143,7 @@ constructor( .get() .setPosition(change.leash, animBounds.left.toFloat(), animBounds.top.toFloat()) .setScale(change.leash, animScale, animScale) .setFrameTimeline(Choreographer.getInstance().vsyncId) .apply() } } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandlerTest.kt +3 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WindowingMode import android.os.Handler import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.SurfaceControl Loading Loading @@ -52,6 +53,7 @@ class CloseDesktopTaskTransitionHandlerTest : ShellTestCase() { @Mock lateinit var testExecutor: ShellExecutor @Mock lateinit var closingTaskLeash: SurfaceControl @Mock lateinit var mockHandler: Handler private val transactionSupplier = Supplier { mock<SurfaceControl.Transaction>() } Loading @@ -65,6 +67,7 @@ class CloseDesktopTaskTransitionHandlerTest : ShellTestCase() { testExecutor, testExecutor, transactionSupplier, mockHandler, ) } Loading Loading
core/java/com/android/internal/jank/Cuj.java +15 −2 Original line number Diff line number Diff line Loading @@ -265,8 +265,17 @@ public class Cuj { */ public static final int CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS = 121; /** * Track closing task in Desktop Windowing. * * <p> Tracking begins when the CloseDesktopTaskTransitionHandler in Launcher starts * animating the task closure. This is triggered when the close button in the app header is * clicked on a desktop window. </p> */ public static final int CUJ_DESKTOP_MODE_CLOSE_TASK = 122; // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. @VisibleForTesting static final int LAST_CUJ = CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS; @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_CLOSE_TASK; /** @hide */ @IntDef({ Loading Loading @@ -379,7 +388,8 @@ public class Cuj { CUJ_DESKTOP_MODE_SNAP_RESIZE, CUJ_DESKTOP_MODE_UNMAXIMIZE_WINDOW, CUJ_DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU, CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS, CUJ_DESKTOP_MODE_CLOSE_TASK }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} Loading Loading @@ -503,6 +513,7 @@ public class Cuj { CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_UNMAXIMIZE_WINDOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_UNMAXIMIZE_WINDOW; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OVERVIEW_TASK_DISMISS; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_CLOSE_TASK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_CLOSE_TASK; } private Cuj() { Loading Loading @@ -741,6 +752,8 @@ public class Cuj { return "DESKTOP_MODE_ENTER_FROM_OVERVIEW_MENU"; case CUJ_LAUNCHER_OVERVIEW_TASK_DISMISS: return "LAUNCHER_OVERVIEW_TASK_DISMISS"; case CUJ_DESKTOP_MODE_CLOSE_TASK: return "DESKTOP_MODE_CLOSE_TASK"; } return "UNKNOWN"; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −2 Original line number Diff line number Diff line Loading @@ -1031,8 +1031,9 @@ public abstract class WMShellModule { static CloseDesktopTaskTransitionHandler provideCloseDesktopTaskTransitionHandler( Context context, @ShellMainThread ShellExecutor mainExecutor, @ShellAnimationThread ShellExecutor animExecutor) { return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor); @ShellAnimationThread ShellExecutor animExecutor, @ShellMainThread Handler handler) { return new CloseDesktopTaskTransitionHandler(context, mainExecutor, animExecutor, handler); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandler.kt +23 −6 Original line number Diff line number Diff line Loading @@ -23,8 +23,10 @@ import android.animation.ValueAnimator import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.content.Context import android.graphics.Rect import android.os.Handler import android.os.IBinder import android.util.TypedValue import android.view.Choreographer import android.view.SurfaceControl.Transaction import android.view.WindowManager import android.window.TransitionInfo Loading @@ -32,7 +34,10 @@ import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import androidx.core.animation.addListener import com.android.app.animation.Interpolators import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_CLOSE_TASK import com.android.internal.jank.InteractionJankMonitor import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.Transitions import java.util.function.Supplier Loading @@ -44,9 +49,11 @@ constructor( private val mainExecutor: ShellExecutor, private val animExecutor: ShellExecutor, private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() }, @ShellMainThread private val handler: Handler, ) : Transitions.TransitionHandler { private val runningAnimations = mutableMapOf<IBinder, List<Animator>>() private val interactionJankMonitor = InteractionJankMonitor.getInstance() /** Returns null, as it only handles transitions started from Shell. */ override fun handleRequest( Loading @@ -71,18 +78,27 @@ constructor( // All animations completed, finish the transition runningAnimations.remove(transition) finishCallback.onTransitionFinished(/* wct= */ null) interactionJankMonitor.end(CUJ_DESKTOP_MODE_CLOSE_TASK) } } } animations += info.changes .filter { val closingChanges = info.changes.filter { it.mode == WindowManager.TRANSIT_CLOSE && it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM } .map { createCloseAnimation(it, finishTransaction, onAnimFinish) } animations += closingChanges.map { createCloseAnimation(it, finishTransaction, onAnimFinish) } if (animations.isEmpty()) return false runningAnimations[transition] = animations closingChanges.lastOrNull()?.leash?.let { lastChangeLeash -> interactionJankMonitor.begin( lastChangeLeash, context, handler, CUJ_DESKTOP_MODE_CLOSE_TASK, ) } animExecutor.execute { animations.forEach(Animator::start) } return true } Loading Loading @@ -127,6 +143,7 @@ constructor( .get() .setPosition(change.leash, animBounds.left.toFloat(), animBounds.top.toFloat()) .setScale(change.leash, animScale, animScale) .setFrameTimeline(Choreographer.getInstance().vsyncId) .apply() } } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/CloseDesktopTaskTransitionHandlerTest.kt +3 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WindowingMode import android.os.Handler import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.SurfaceControl Loading Loading @@ -52,6 +53,7 @@ class CloseDesktopTaskTransitionHandlerTest : ShellTestCase() { @Mock lateinit var testExecutor: ShellExecutor @Mock lateinit var closingTaskLeash: SurfaceControl @Mock lateinit var mockHandler: Handler private val transactionSupplier = Supplier { mock<SurfaceControl.Transaction>() } Loading @@ -65,6 +67,7 @@ class CloseDesktopTaskTransitionHandlerTest : ShellTestCase() { testExecutor, testExecutor, transactionSupplier, mockHandler, ) } Loading