Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +9 −2 Original line number Diff line number Diff line Loading @@ -566,7 +566,8 @@ public abstract class WMShellModule { Context context, Transitions transitions, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, ShellTaskOrganizer shellTaskOrganizer) { ShellTaskOrganizer shellTaskOrganizer, InteractionJankMonitor interactionJankMonitor) { int maxTaskLimit = DesktopModeStatus.getMaxTaskLimit(context); if (!DesktopModeStatus.canEnterDesktopMode(context) || !ENABLE_DESKTOP_WINDOWING_TASK_LIMIT.isEnabled(context) Loading @@ -575,7 +576,13 @@ public abstract class WMShellModule { } return Optional.of( new DesktopTasksLimiter( transitions, desktopModeTaskRepository, shellTaskOrganizer, maxTaskLimit)); transitions, desktopModeTaskRepository, shellTaskOrganizer, maxTaskLimit, interactionJankMonitor, context) ); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt +35 −3 Original line number Diff line number Diff line Loading @@ -17,12 +17,15 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.content.Context import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_TO_BACK import android.window.TransitionInfo import android.window.WindowContainerTransaction import androidx.annotation.VisibleForTesting import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup Loading @@ -41,6 +44,8 @@ class DesktopTasksLimiter ( private val taskRepository: DesktopModeTaskRepository, private val shellTaskOrganizer: ShellTaskOrganizer, private val maxTasksLimit: Int, private val interactionJankMonitor: InteractionJankMonitor, private val context: Context ) { private val minimizeTransitionObserver = MinimizeTransitionObserver() @VisibleForTesting Loading @@ -57,11 +62,16 @@ class DesktopTasksLimiter ( "DesktopTasksLimiter: starting limiter with a maximum of %d tasks", maxTasksLimit) } private data class TaskDetails (val displayId: Int, val taskId: Int) private data class TaskDetails( val displayId: Int, val taskId: Int, var transitionInfo: TransitionInfo? ) // TODO(b/333018485): replace this observer when implementing the minimize-animation private inner class MinimizeTransitionObserver : TransitionObserver { private val mPendingTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>() private val mActiveTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>() fun addPendingTransitionToken(transition: IBinder, taskDetails: TaskDetails) { mPendingTransitionTokensAndTasks[transition] = taskDetails Loading @@ -74,6 +84,8 @@ class DesktopTasksLimiter ( finishTransaction: SurfaceControl.Transaction ) { val taskToMinimize = mPendingTransitionTokensAndTasks.remove(transition) ?: return taskToMinimize.transitionInfo = info mActiveTransitionTokensAndTasks[transition] = taskToMinimize if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return Loading @@ -84,6 +96,7 @@ class DesktopTasksLimiter ( taskToMinimize.taskId) return } this@DesktopTasksLimiter.markTaskMinimized( taskToMinimize.displayId, taskToMinimize.taskId) } Loading @@ -107,9 +120,21 @@ class DesktopTasksLimiter ( return taskChange.mode == TRANSIT_TO_BACK } override fun onTransitionStarting(transition: IBinder) {} override fun onTransitionStarting(transition: IBinder) { val mActiveTaskDetails = mActiveTransitionTokensAndTasks[transition] if (mActiveTaskDetails != null && mActiveTaskDetails.transitionInfo != null) { // Begin minimize window CUJ instrumentation. interactionJankMonitor.begin( mActiveTaskDetails.transitionInfo?.rootLeash, context, CUJ_DESKTOP_MODE_MINIMIZE_WINDOW ) } } override fun onTransitionMerged(merged: IBinder, playing: IBinder) { if (mActiveTransitionTokensAndTasks.remove(merged) != null) { interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) } mPendingTransitionTokensAndTasks.remove(merged)?.let { taskToTransfer -> mPendingTransitionTokensAndTasks[playing] = taskToTransfer } Loading @@ -119,6 +144,13 @@ class DesktopTasksLimiter ( ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: transition %s finished", transition) if (mActiveTransitionTokensAndTasks.remove(transition) != null) { if (aborted) { interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) } else { interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) } } mPendingTransitionTokensAndTasks.remove(transition) } } Loading Loading @@ -196,7 +228,7 @@ class DesktopTasksLimiter ( */ fun addPendingMinimizeChange(transition: IBinder, displayId: Int, taskId: Int) { minimizeTransitionObserver.addPendingTransitionToken( transition, TaskDetails(displayId, taskId)) transition, TaskDetails(displayId, taskId, transitionInfo = null)) } /** Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +2 −1 Original line number Diff line number Diff line Loading @@ -211,7 +211,8 @@ class DesktopTasksControllerTest : ShellTestCase() { taskRepository, shellTaskOrganizer, MAX_TASK_LIMIT, ) mockInteractionJankMonitor, mContext) whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks } whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt +98 −4 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask Loading @@ -47,6 +49,8 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.any import org.mockito.Mockito.`when` import org.mockito.kotlin.eq import org.mockito.kotlin.verify import org.mockito.quality.Strictness Loading @@ -65,6 +69,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer @Mock lateinit var transitions: Transitions @Mock lateinit var interactionJankMonitor: InteractionJankMonitor private lateinit var mockitoSession: StaticMockitoSession private lateinit var desktopTasksLimiter: DesktopTasksLimiter Loading @@ -79,7 +84,8 @@ class DesktopTasksLimiterTest : ShellTestCase() { desktopTaskRepo = DesktopModeTaskRepository() desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT, interactionJankMonitor, mContext) } @After Loading @@ -90,14 +96,16 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Test fun createDesktopTasksLimiter_withZeroLimit_shouldThrow() { assertFailsWith<IllegalArgumentException> { DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0, interactionJankMonitor, mContext) } } @Test fun createDesktopTasksLimiter_withNegativeLimit_shouldThrow() { assertFailsWith<IllegalArgumentException> { DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5, interactionJankMonitor, mContext) } } Loading Loading @@ -325,7 +333,8 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Test fun getTaskToMinimizeIfNeeded_tasksAboveLimit_otherLimit_returnsBackTask() { desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2, interactionJankMonitor, mContext) val tasks = (1..MAX_TASK_LIMIT2 + 1).map { setUpFreeformTask() } val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded( Loading @@ -347,6 +356,91 @@ class DesktopTasksLimiterTest : ShellTestCase() { assertThat(minimizedTask).isEqualTo(tasks.last()) } @Test fun minimizeTransitionReadyAndFinished_logsJankInstrumentationBeginAndEnd() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } val transition = Binder() val task = setUpFreeformTask() desktopTasksLimiter.addPendingMinimizeChange( transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId) desktopTasksLimiter.getTransitionObserver().onTransitionReady( transition, TransitionInfoBuilder(TRANSIT_OPEN).build(), StubTransaction() /* startTransaction */, StubTransaction() /* finishTransaction */) desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition) verify(interactionJankMonitor).begin( any(), eq(mContext), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionFinished( transition, /* aborted = */ false) verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) } @Test fun minimizeTransitionReadyAndAborted_logsJankInstrumentationBeginAndCancel() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } val transition = Binder() val task = setUpFreeformTask() desktopTasksLimiter.addPendingMinimizeChange( transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId) desktopTasksLimiter.getTransitionObserver().onTransitionReady( transition, TransitionInfoBuilder(TRANSIT_OPEN).build(), StubTransaction() /* startTransaction */, StubTransaction() /* finishTransaction */) desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition) verify(interactionJankMonitor).begin( any(), eq(mContext), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionFinished( transition, /* aborted = */ true) verify(interactionJankMonitor).cancel(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) } @Test fun minimizeTransitionReadyAndMerged_logsJankInstrumentationBeginAndEnd() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } val mergedTransition = Binder() val newTransition = Binder() val task = setUpFreeformTask() desktopTasksLimiter.addPendingMinimizeChange( mergedTransition, displayId = DEFAULT_DISPLAY, taskId = task.taskId) desktopTasksLimiter.getTransitionObserver().onTransitionReady( mergedTransition, TransitionInfoBuilder(TRANSIT_OPEN).build(), StubTransaction() /* startTransaction */, StubTransaction() /* finishTransaction */) desktopTasksLimiter.getTransitionObserver().onTransitionStarting(mergedTransition) verify(interactionJankMonitor).begin( any(), eq(mContext), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionMerged( mergedTransition, newTransition) verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) } private fun setUpFreeformTask( displayId: Int = DEFAULT_DISPLAY, ): RunningTaskInfo { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +9 −2 Original line number Diff line number Diff line Loading @@ -566,7 +566,8 @@ public abstract class WMShellModule { Context context, Transitions transitions, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, ShellTaskOrganizer shellTaskOrganizer) { ShellTaskOrganizer shellTaskOrganizer, InteractionJankMonitor interactionJankMonitor) { int maxTaskLimit = DesktopModeStatus.getMaxTaskLimit(context); if (!DesktopModeStatus.canEnterDesktopMode(context) || !ENABLE_DESKTOP_WINDOWING_TASK_LIMIT.isEnabled(context) Loading @@ -575,7 +576,13 @@ public abstract class WMShellModule { } return Optional.of( new DesktopTasksLimiter( transitions, desktopModeTaskRepository, shellTaskOrganizer, maxTaskLimit)); transitions, desktopModeTaskRepository, shellTaskOrganizer, maxTaskLimit, interactionJankMonitor, context) ); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt +35 −3 Original line number Diff line number Diff line Loading @@ -17,12 +17,15 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.content.Context import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_TO_BACK import android.window.TransitionInfo import android.window.WindowContainerTransaction import androidx.annotation.VisibleForTesting import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup Loading @@ -41,6 +44,8 @@ class DesktopTasksLimiter ( private val taskRepository: DesktopModeTaskRepository, private val shellTaskOrganizer: ShellTaskOrganizer, private val maxTasksLimit: Int, private val interactionJankMonitor: InteractionJankMonitor, private val context: Context ) { private val minimizeTransitionObserver = MinimizeTransitionObserver() @VisibleForTesting Loading @@ -57,11 +62,16 @@ class DesktopTasksLimiter ( "DesktopTasksLimiter: starting limiter with a maximum of %d tasks", maxTasksLimit) } private data class TaskDetails (val displayId: Int, val taskId: Int) private data class TaskDetails( val displayId: Int, val taskId: Int, var transitionInfo: TransitionInfo? ) // TODO(b/333018485): replace this observer when implementing the minimize-animation private inner class MinimizeTransitionObserver : TransitionObserver { private val mPendingTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>() private val mActiveTransitionTokensAndTasks = mutableMapOf<IBinder, TaskDetails>() fun addPendingTransitionToken(transition: IBinder, taskDetails: TaskDetails) { mPendingTransitionTokensAndTasks[transition] = taskDetails Loading @@ -74,6 +84,8 @@ class DesktopTasksLimiter ( finishTransaction: SurfaceControl.Transaction ) { val taskToMinimize = mPendingTransitionTokensAndTasks.remove(transition) ?: return taskToMinimize.transitionInfo = info mActiveTransitionTokensAndTasks[transition] = taskToMinimize if (!taskRepository.isActiveTask(taskToMinimize.taskId)) return Loading @@ -84,6 +96,7 @@ class DesktopTasksLimiter ( taskToMinimize.taskId) return } this@DesktopTasksLimiter.markTaskMinimized( taskToMinimize.displayId, taskToMinimize.taskId) } Loading @@ -107,9 +120,21 @@ class DesktopTasksLimiter ( return taskChange.mode == TRANSIT_TO_BACK } override fun onTransitionStarting(transition: IBinder) {} override fun onTransitionStarting(transition: IBinder) { val mActiveTaskDetails = mActiveTransitionTokensAndTasks[transition] if (mActiveTaskDetails != null && mActiveTaskDetails.transitionInfo != null) { // Begin minimize window CUJ instrumentation. interactionJankMonitor.begin( mActiveTaskDetails.transitionInfo?.rootLeash, context, CUJ_DESKTOP_MODE_MINIMIZE_WINDOW ) } } override fun onTransitionMerged(merged: IBinder, playing: IBinder) { if (mActiveTransitionTokensAndTasks.remove(merged) != null) { interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) } mPendingTransitionTokensAndTasks.remove(merged)?.let { taskToTransfer -> mPendingTransitionTokensAndTasks[playing] = taskToTransfer } Loading @@ -119,6 +144,13 @@ class DesktopTasksLimiter ( ProtoLog.v( ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "DesktopTasksLimiter: transition %s finished", transition) if (mActiveTransitionTokensAndTasks.remove(transition) != null) { if (aborted) { interactionJankMonitor.cancel(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) } else { interactionJankMonitor.end(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW) } } mPendingTransitionTokensAndTasks.remove(transition) } } Loading Loading @@ -196,7 +228,7 @@ class DesktopTasksLimiter ( */ fun addPendingMinimizeChange(transition: IBinder, displayId: Int, taskId: Int) { minimizeTransitionObserver.addPendingTransitionToken( transition, TaskDetails(displayId, taskId)) transition, TaskDetails(displayId, taskId, transitionInfo = null)) } /** Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +2 −1 Original line number Diff line number Diff line Loading @@ -211,7 +211,8 @@ class DesktopTasksControllerTest : ShellTestCase() { taskRepository, shellTaskOrganizer, MAX_TASK_LIMIT, ) mockInteractionJankMonitor, mContext) whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks } whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt +98 −4 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask Loading @@ -47,6 +49,8 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.any import org.mockito.Mockito.`when` import org.mockito.kotlin.eq import org.mockito.kotlin.verify import org.mockito.quality.Strictness Loading @@ -65,6 +69,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer @Mock lateinit var transitions: Transitions @Mock lateinit var interactionJankMonitor: InteractionJankMonitor private lateinit var mockitoSession: StaticMockitoSession private lateinit var desktopTasksLimiter: DesktopTasksLimiter Loading @@ -79,7 +84,8 @@ class DesktopTasksLimiterTest : ShellTestCase() { desktopTaskRepo = DesktopModeTaskRepository() desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT, interactionJankMonitor, mContext) } @After Loading @@ -90,14 +96,16 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Test fun createDesktopTasksLimiter_withZeroLimit_shouldThrow() { assertFailsWith<IllegalArgumentException> { DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0, interactionJankMonitor, mContext) } } @Test fun createDesktopTasksLimiter_withNegativeLimit_shouldThrow() { assertFailsWith<IllegalArgumentException> { DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5, interactionJankMonitor, mContext) } } Loading Loading @@ -325,7 +333,8 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Test fun getTaskToMinimizeIfNeeded_tasksAboveLimit_otherLimit_returnsBackTask() { desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2) DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2, interactionJankMonitor, mContext) val tasks = (1..MAX_TASK_LIMIT2 + 1).map { setUpFreeformTask() } val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded( Loading @@ -347,6 +356,91 @@ class DesktopTasksLimiterTest : ShellTestCase() { assertThat(minimizedTask).isEqualTo(tasks.last()) } @Test fun minimizeTransitionReadyAndFinished_logsJankInstrumentationBeginAndEnd() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } val transition = Binder() val task = setUpFreeformTask() desktopTasksLimiter.addPendingMinimizeChange( transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId) desktopTasksLimiter.getTransitionObserver().onTransitionReady( transition, TransitionInfoBuilder(TRANSIT_OPEN).build(), StubTransaction() /* startTransaction */, StubTransaction() /* finishTransaction */) desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition) verify(interactionJankMonitor).begin( any(), eq(mContext), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionFinished( transition, /* aborted = */ false) verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) } @Test fun minimizeTransitionReadyAndAborted_logsJankInstrumentationBeginAndCancel() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } val transition = Binder() val task = setUpFreeformTask() desktopTasksLimiter.addPendingMinimizeChange( transition, displayId = DEFAULT_DISPLAY, taskId = task.taskId) desktopTasksLimiter.getTransitionObserver().onTransitionReady( transition, TransitionInfoBuilder(TRANSIT_OPEN).build(), StubTransaction() /* startTransaction */, StubTransaction() /* finishTransaction */) desktopTasksLimiter.getTransitionObserver().onTransitionStarting(transition) verify(interactionJankMonitor).begin( any(), eq(mContext), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionFinished( transition, /* aborted = */ true) verify(interactionJankMonitor).cancel(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) } @Test fun minimizeTransitionReadyAndMerged_logsJankInstrumentationBeginAndEnd() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } val mergedTransition = Binder() val newTransition = Binder() val task = setUpFreeformTask() desktopTasksLimiter.addPendingMinimizeChange( mergedTransition, displayId = DEFAULT_DISPLAY, taskId = task.taskId) desktopTasksLimiter.getTransitionObserver().onTransitionReady( mergedTransition, TransitionInfoBuilder(TRANSIT_OPEN).build(), StubTransaction() /* startTransaction */, StubTransaction() /* finishTransaction */) desktopTasksLimiter.getTransitionObserver().onTransitionStarting(mergedTransition) verify(interactionJankMonitor).begin( any(), eq(mContext), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionMerged( mergedTransition, newTransition) verify(interactionJankMonitor).end(eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) } private fun setUpFreeformTask( displayId: Int = DEFAULT_DISPLAY, ): RunningTaskInfo { Loading