Loading core/java/com/android/internal/jank/Cuj.java +14 −3 Original line number Diff line number Diff line Loading @@ -416,8 +416,16 @@ public class Cuj { */ public static final int CUJ_WEAR_NOTIFICATION_TRAY_OPEN = 137; /** * Tracking when notification shade window gets moved between displays * * <p>Tracking starts when the notification shade starts to move to a new display, and ends * when the notification shade is fully expanded in the new display. */ public static final int CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE = 138; // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. @VisibleForTesting static final int LAST_CUJ = CUJ_WEAR_NOTIFICATION_TRAY_OPEN; @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE; /** @hide */ @IntDef({ Loading Loading @@ -546,8 +554,8 @@ public class Cuj { CUJ_WEAR_CAROUSEL_FLING_JANK, CUJ_WEAR_CAROUSEL_SWIPE_JANK, CUJ_WEAR_QSS_TRAY_OPEN, CUJ_WEAR_NOTIFICATION_TRAY_OPEN CUJ_WEAR_NOTIFICATION_TRAY_OPEN, CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} Loading Loading @@ -687,6 +695,7 @@ public class Cuj { CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WEAR_CAROUSEL_SWIPE_JANK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WEAR_CAROUSEL_SWIPE_JANK; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WEAR_QSS_TRAY_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WEAR_QSS_TRAY_OPEN; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WEAR_NOTIFICATION_TRAY_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WEAR_NOTIFICATION_TRAY_OPEN; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE; } private Cuj() { Loading Loading @@ -957,6 +966,8 @@ public class Cuj { return "WEAR_QSS_TRAY_OPEN"; case CUJ_WEAR_NOTIFICATION_TRAY_OPEN: return "WEAR_NOTIFICATION_TRAY_OPEN"; case CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE: return "DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE"; } return "UNKNOWN"; } Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangePerformanceTrackerTest.kt +80 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import com.android.internal.logging.latencyTracker import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.common.ui.view.fakeChoreographerUtils import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos Loading @@ -30,6 +31,7 @@ import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify Loading @@ -38,14 +40,16 @@ import org.mockito.kotlin.any @SmallTest @RunWith(AndroidJUnit4::class) @android.platform.test.annotations.EnabledOnRavenwood class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { class ShadeDisplayChangePerformanceTrackerTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val configurationRepository = kosmos.fakeConfigurationRepository private val latencyTracker = kosmos.latencyTracker private val jankMonitor = kosmos.interactionJankMonitor private val testScope = kosmos.testScope private val choreographerUtils = kosmos.fakeChoreographerUtils private val shadeTestUtil = kosmos.shadeTestUtil private val underTest = kosmos.shadeDisplayChangeLatencyTracker private val underTest = kosmos.shadeDisplayChangePerformanceTracker @Test fun onShadeDisplayChanging_afterMovedToDisplayAndDoFrameCompleted_atomReported() = Loading @@ -61,6 +65,28 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { verify(latencyTracker).onActionEnd(any()) } @Test fun onShadeDisplayChanging_jankCujBegins() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) } @Test fun onShadeDisplayChanging_afterShadeExpansion_jankCujEnd() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) sendOnMovedToDisplay(1) choreographerUtils.completeDoFrame() shadeTestUtil.setShadeExpansion(1f) verify(jankMonitor).end(anyInt()) } @Test fun onChange_doFrameTimesOut_previousCancelled() = testScope.runTest { Loading @@ -87,10 +113,25 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { advanceTimeBy(100.seconds) verify(latencyTracker).onActionCancel(any()) verify(jankMonitor).cancel(anyInt()) } @Test fun onChange_whilePreviousWasInProgress_previousCancelledAndNewStarted() = fun onChange_onShadeExpandedTimesOut_cancelled() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) sendOnMovedToDisplay(1) choreographerUtils.completeDoFrame() advanceTimeBy(100.seconds) verify(jankMonitor).cancel(anyInt()) } @Test fun onChange_whilePreviousWasInProgress_previousLatencyRecordCancelledAndNewStarted() = testScope.runTest { underTest.onShadeDisplayChanging(1) Loading @@ -103,7 +144,20 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { } @Test fun onChange_multiple_multipleReported() = fun onChange_whilePreviousWasInProgress_previousJankRecordCancelledAndNewStarted() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) underTest.onShadeDisplayChanging(2) verify(jankMonitor).cancel(anyInt()) verify(jankMonitor, times(2)).begin(any(), anyInt()) } @Test fun onChange_multiple_multipleLatencyRecordReported() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(latencyTracker).onActionStart(any()) Loading @@ -122,6 +176,28 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { verify(latencyTracker, times(2)).onActionEnd(any()) } @Test fun onChange_multiple_multipleJankRecordReported() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) sendOnMovedToDisplay(1) choreographerUtils.completeDoFrame() shadeTestUtil.setShadeExpansion(1f) verify(jankMonitor).end(anyInt()) underTest.onShadeDisplayChanging(0) sendOnMovedToDisplay(0) choreographerUtils.completeDoFrame() shadeTestUtil.setShadeExpansion(1f) verify(jankMonitor, times(2)).begin(any(), anyInt()) verify(jankMonitor, times(2)).end(anyInt()) } private fun sendOnMovedToDisplay(displayId: Int) { configurationRepository.onMovedToDisplay(displayId) } Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt +3 −3 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { private val positionRepository = kosmos.fakeShadeDisplaysRepository private val shadeContext = kosmos.mockedWindowContext private val resources = kosmos.mockResources private val latencyTracker = kosmos.mockedShadeDisplayChangeLatencyTracker private val performanceTracker = kosmos.mockedShadeDisplayChangePerformanceTracker private val configuration = mock<Configuration>() private val display = mock<Display>() private val activeNotificationRepository = kosmos.activeNotificationListRepository Loading Loading @@ -104,14 +104,14 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { } @Test fun start_shadeInWrongPosition_logsStartToLatencyTracker() = fun start_shadeInWrongPosition_logsStartToPerformanceTracker() = testScope.runTest { whenever(display.displayId).thenReturn(0) positionRepository.setPendingDisplayId(1) underTest.start() verify(latencyTracker).onShadeDisplayChanging(eq(1)) verify(performanceTracker).onShadeDisplayChanging(eq(1)) } @Test Loading packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTracker.kt→packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangePerformanceTracker.kt +22 −9 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ package com.android.systemui.shade import android.util.Log import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE import com.android.internal.jank.InteractionJankMonitor import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.domain.interactor.ShadeDisplaysWaitInteractor import java.util.concurrent.CancellationException Loading @@ -30,21 +33,23 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeout /** * Tracks the time it takes to move the shade from one display to another. * - The start event is when [ShadeDisplaysRepository] propagates the new display ID. * - The end event is one frame after the shade configuration controller receives a new * configuration change. * * Note that even in the unlikely case the configuration of the new display is the same, * onConfigurationChange is called anyway as is is triggered by * Records the performance of moving the shade from one display to another - tracking both the * latency and jank involved in the process. * - Recording starts when [ShadeDisplaysRepository] propagates the new display ID. * - Latency tracking ends one frame after the shade configuration controller receives a new * configuration change. (Note: even if the configuration of the new display is the same, * onConfigurationChange is called anyway as it is triggered by * [NotificationShadeWindowView.onMovedToDisplay]. * - Jank tracking ends after the shade window is fully expanded. */ @SysUISingleton class ShadeDisplayChangeLatencyTracker class ShadeDisplayChangePerformanceTracker @Inject constructor( private val latencyTracker: LatencyTracker, private val shadeRootView: WindowRootView, @Background private val bgScope: CoroutineScope, private val jankMonitor: InteractionJankMonitor, private val waitInteractor: ShadeDisplaysWaitInteractor, ) { Loading @@ -69,10 +74,13 @@ constructor( private suspend fun onShadeDisplayChangingAsync(displayId: Int) { try { jankMonitor.begin(shadeRootView, CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE) latencyTracker.onActionStart(SHADE_MOVE_ACTION) waitForOnMovedToDisplayDispatchedToView(displayId) waitUntilNextDoFrameDone(displayId) latencyTracker.onActionEnd(SHADE_MOVE_ACTION) waitForShadeExpanded() jankMonitor.end(CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE) } catch (e: Exception) { val reason = when (e) { Loading @@ -84,6 +92,7 @@ constructor( } Log.e(TAG, reason, e) latencyTracker.onActionCancel(SHADE_MOVE_ACTION) jankMonitor.cancel(CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE) } } Loading @@ -97,6 +106,10 @@ constructor( withTimeout(TIMEOUT) { waitInteractor.waitForNextDoFrameDone(newDisplayId, TAG) } } private suspend fun waitForShadeExpanded() { withTimeout(TIMEOUT) { waitInteractor.waitForShadeExpanded(TAG) } } private companion object { const val TAG = "ShadeDisplayLatency" val TIMEOUT = 3.seconds Loading packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt +3 −3 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.shade.ShadeDisplayChangeLatencyTracker import com.android.systemui.shade.ShadeDisplayChangePerformanceTracker import com.android.systemui.shade.ShadeDisplayLog import com.android.systemui.shade.ShadeTraceLogger.logMoveShadeWindowTo import com.android.systemui.shade.ShadeTraceLogger.t Loading Loading @@ -72,7 +72,7 @@ constructor( @ShadeDisplayAware private val shadeContext: WindowContext, @Background private val bgScope: CoroutineScope, @Main private val mainThreadContext: CoroutineContext, private val shadeDisplayChangeLatencyTracker: ShadeDisplayChangeLatencyTracker, private val shadeDisplayChangePerformanceTracker: ShadeDisplayChangePerformanceTracker, private val shadeExpandedInteractor: ShadeExpandedStateInteractor, private val shadeExpansionIntent: ShadeExpansionIntent, private val activeNotificationsInteractor: ActiveNotificationsInteractor, Loading Loading @@ -142,7 +142,7 @@ constructor( withContext(mainThreadContext) { traceReparenting { collapseAndExpandShadeIfNeeded(destinationId) { shadeDisplayChangeLatencyTracker.onShadeDisplayChanging(destinationId) shadeDisplayChangePerformanceTracker.onShadeDisplayChanging(destinationId) reparentToDisplayId(id = destinationId) } checkContextDisplayMatchesExpected(destinationId) Loading Loading
core/java/com/android/internal/jank/Cuj.java +14 −3 Original line number Diff line number Diff line Loading @@ -416,8 +416,16 @@ public class Cuj { */ public static final int CUJ_WEAR_NOTIFICATION_TRAY_OPEN = 137; /** * Tracking when notification shade window gets moved between displays * * <p>Tracking starts when the notification shade starts to move to a new display, and ends * when the notification shade is fully expanded in the new display. */ public static final int CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE = 138; // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. @VisibleForTesting static final int LAST_CUJ = CUJ_WEAR_NOTIFICATION_TRAY_OPEN; @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE; /** @hide */ @IntDef({ Loading Loading @@ -546,8 +554,8 @@ public class Cuj { CUJ_WEAR_CAROUSEL_FLING_JANK, CUJ_WEAR_CAROUSEL_SWIPE_JANK, CUJ_WEAR_QSS_TRAY_OPEN, CUJ_WEAR_NOTIFICATION_TRAY_OPEN CUJ_WEAR_NOTIFICATION_TRAY_OPEN, CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} Loading Loading @@ -687,6 +695,7 @@ public class Cuj { CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WEAR_CAROUSEL_SWIPE_JANK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WEAR_CAROUSEL_SWIPE_JANK; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WEAR_QSS_TRAY_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WEAR_QSS_TRAY_OPEN; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WEAR_NOTIFICATION_TRAY_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WEAR_NOTIFICATION_TRAY_OPEN; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE; } private Cuj() { Loading Loading @@ -957,6 +966,8 @@ public class Cuj { return "WEAR_QSS_TRAY_OPEN"; case CUJ_WEAR_NOTIFICATION_TRAY_OPEN: return "WEAR_NOTIFICATION_TRAY_OPEN"; case CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE: return "DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE"; } return "UNKNOWN"; } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangePerformanceTrackerTest.kt +80 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import com.android.internal.logging.latencyTracker import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.common.ui.view.fakeChoreographerUtils import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos Loading @@ -30,6 +31,7 @@ import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify Loading @@ -38,14 +40,16 @@ import org.mockito.kotlin.any @SmallTest @RunWith(AndroidJUnit4::class) @android.platform.test.annotations.EnabledOnRavenwood class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { class ShadeDisplayChangePerformanceTrackerTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val configurationRepository = kosmos.fakeConfigurationRepository private val latencyTracker = kosmos.latencyTracker private val jankMonitor = kosmos.interactionJankMonitor private val testScope = kosmos.testScope private val choreographerUtils = kosmos.fakeChoreographerUtils private val shadeTestUtil = kosmos.shadeTestUtil private val underTest = kosmos.shadeDisplayChangeLatencyTracker private val underTest = kosmos.shadeDisplayChangePerformanceTracker @Test fun onShadeDisplayChanging_afterMovedToDisplayAndDoFrameCompleted_atomReported() = Loading @@ -61,6 +65,28 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { verify(latencyTracker).onActionEnd(any()) } @Test fun onShadeDisplayChanging_jankCujBegins() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) } @Test fun onShadeDisplayChanging_afterShadeExpansion_jankCujEnd() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) sendOnMovedToDisplay(1) choreographerUtils.completeDoFrame() shadeTestUtil.setShadeExpansion(1f) verify(jankMonitor).end(anyInt()) } @Test fun onChange_doFrameTimesOut_previousCancelled() = testScope.runTest { Loading @@ -87,10 +113,25 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { advanceTimeBy(100.seconds) verify(latencyTracker).onActionCancel(any()) verify(jankMonitor).cancel(anyInt()) } @Test fun onChange_whilePreviousWasInProgress_previousCancelledAndNewStarted() = fun onChange_onShadeExpandedTimesOut_cancelled() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) sendOnMovedToDisplay(1) choreographerUtils.completeDoFrame() advanceTimeBy(100.seconds) verify(jankMonitor).cancel(anyInt()) } @Test fun onChange_whilePreviousWasInProgress_previousLatencyRecordCancelledAndNewStarted() = testScope.runTest { underTest.onShadeDisplayChanging(1) Loading @@ -103,7 +144,20 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { } @Test fun onChange_multiple_multipleReported() = fun onChange_whilePreviousWasInProgress_previousJankRecordCancelledAndNewStarted() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) underTest.onShadeDisplayChanging(2) verify(jankMonitor).cancel(anyInt()) verify(jankMonitor, times(2)).begin(any(), anyInt()) } @Test fun onChange_multiple_multipleLatencyRecordReported() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(latencyTracker).onActionStart(any()) Loading @@ -122,6 +176,28 @@ class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() { verify(latencyTracker, times(2)).onActionEnd(any()) } @Test fun onChange_multiple_multipleJankRecordReported() = testScope.runTest { underTest.onShadeDisplayChanging(1) verify(jankMonitor).begin(any(), anyInt()) sendOnMovedToDisplay(1) choreographerUtils.completeDoFrame() shadeTestUtil.setShadeExpansion(1f) verify(jankMonitor).end(anyInt()) underTest.onShadeDisplayChanging(0) sendOnMovedToDisplay(0) choreographerUtils.completeDoFrame() shadeTestUtil.setShadeExpansion(1f) verify(jankMonitor, times(2)).begin(any(), anyInt()) verify(jankMonitor, times(2)).end(anyInt()) } private fun sendOnMovedToDisplay(displayId: Int) { configurationRepository.onMovedToDisplay(displayId) } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt +3 −3 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { private val positionRepository = kosmos.fakeShadeDisplaysRepository private val shadeContext = kosmos.mockedWindowContext private val resources = kosmos.mockResources private val latencyTracker = kosmos.mockedShadeDisplayChangeLatencyTracker private val performanceTracker = kosmos.mockedShadeDisplayChangePerformanceTracker private val configuration = mock<Configuration>() private val display = mock<Display>() private val activeNotificationRepository = kosmos.activeNotificationListRepository Loading Loading @@ -104,14 +104,14 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { } @Test fun start_shadeInWrongPosition_logsStartToLatencyTracker() = fun start_shadeInWrongPosition_logsStartToPerformanceTracker() = testScope.runTest { whenever(display.displayId).thenReturn(0) positionRepository.setPendingDisplayId(1) underTest.start() verify(latencyTracker).onShadeDisplayChanging(eq(1)) verify(performanceTracker).onShadeDisplayChanging(eq(1)) } @Test Loading
packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTracker.kt→packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangePerformanceTracker.kt +22 −9 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ package com.android.systemui.shade import android.util.Log import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE import com.android.internal.jank.InteractionJankMonitor import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.domain.interactor.ShadeDisplaysWaitInteractor import java.util.concurrent.CancellationException Loading @@ -30,21 +33,23 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeout /** * Tracks the time it takes to move the shade from one display to another. * - The start event is when [ShadeDisplaysRepository] propagates the new display ID. * - The end event is one frame after the shade configuration controller receives a new * configuration change. * * Note that even in the unlikely case the configuration of the new display is the same, * onConfigurationChange is called anyway as is is triggered by * Records the performance of moving the shade from one display to another - tracking both the * latency and jank involved in the process. * - Recording starts when [ShadeDisplaysRepository] propagates the new display ID. * - Latency tracking ends one frame after the shade configuration controller receives a new * configuration change. (Note: even if the configuration of the new display is the same, * onConfigurationChange is called anyway as it is triggered by * [NotificationShadeWindowView.onMovedToDisplay]. * - Jank tracking ends after the shade window is fully expanded. */ @SysUISingleton class ShadeDisplayChangeLatencyTracker class ShadeDisplayChangePerformanceTracker @Inject constructor( private val latencyTracker: LatencyTracker, private val shadeRootView: WindowRootView, @Background private val bgScope: CoroutineScope, private val jankMonitor: InteractionJankMonitor, private val waitInteractor: ShadeDisplaysWaitInteractor, ) { Loading @@ -69,10 +74,13 @@ constructor( private suspend fun onShadeDisplayChangingAsync(displayId: Int) { try { jankMonitor.begin(shadeRootView, CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE) latencyTracker.onActionStart(SHADE_MOVE_ACTION) waitForOnMovedToDisplayDispatchedToView(displayId) waitUntilNextDoFrameDone(displayId) latencyTracker.onActionEnd(SHADE_MOVE_ACTION) waitForShadeExpanded() jankMonitor.end(CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE) } catch (e: Exception) { val reason = when (e) { Loading @@ -84,6 +92,7 @@ constructor( } Log.e(TAG, reason, e) latencyTracker.onActionCancel(SHADE_MOVE_ACTION) jankMonitor.cancel(CUJ_DESKTOP_MODE_SHADE_WINDOW_DISPLAY_CHANGE) } } Loading @@ -97,6 +106,10 @@ constructor( withTimeout(TIMEOUT) { waitInteractor.waitForNextDoFrameDone(newDisplayId, TAG) } } private suspend fun waitForShadeExpanded() { withTimeout(TIMEOUT) { waitInteractor.waitForShadeExpanded(TAG) } } private companion object { const val TAG = "ShadeDisplayLatency" val TIMEOUT = 3.seconds Loading
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt +3 −3 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.shade.ShadeDisplayChangeLatencyTracker import com.android.systemui.shade.ShadeDisplayChangePerformanceTracker import com.android.systemui.shade.ShadeDisplayLog import com.android.systemui.shade.ShadeTraceLogger.logMoveShadeWindowTo import com.android.systemui.shade.ShadeTraceLogger.t Loading Loading @@ -72,7 +72,7 @@ constructor( @ShadeDisplayAware private val shadeContext: WindowContext, @Background private val bgScope: CoroutineScope, @Main private val mainThreadContext: CoroutineContext, private val shadeDisplayChangeLatencyTracker: ShadeDisplayChangeLatencyTracker, private val shadeDisplayChangePerformanceTracker: ShadeDisplayChangePerformanceTracker, private val shadeExpandedInteractor: ShadeExpandedStateInteractor, private val shadeExpansionIntent: ShadeExpansionIntent, private val activeNotificationsInteractor: ActiveNotificationsInteractor, Loading Loading @@ -142,7 +142,7 @@ constructor( withContext(mainThreadContext) { traceReparenting { collapseAndExpandShadeIfNeeded(destinationId) { shadeDisplayChangeLatencyTracker.onShadeDisplayChanging(destinationId) shadeDisplayChangePerformanceTracker.onShadeDisplayChanging(destinationId) reparentToDisplayId(id = destinationId) } checkContextDisplayMatchesExpected(destinationId) Loading