diff options
| author | 2024-08-28 20:23:00 +0000 | |
|---|---|---|
| committer | 2024-08-28 20:23:00 +0000 | |
| commit | 140822a55157de7bc70534f41006da03f96474b8 (patch) | |
| tree | 86d8132761755d1bdfc098db454d045591917ef8 | |
| parent | 30ea5285c3170792242e83d6efc389d7404ca8fa (diff) | |
| parent | 711005ea8d069edb4699d65659fdd0097a5db6f5 (diff) | |
Merge "Adds coroutine tracing to activatables and sysUiViewModels" into main
19 files changed, 95 insertions, 51 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt index 5a4020d3b1fb..270d751d2d3c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt @@ -76,7 +76,7 @@ constructor( modifier: Modifier, ) = BouncerScene( - viewModel = rememberViewModel { contentViewModelFactory.create() }, + viewModel = rememberViewModel("BouncerScene") { contentViewModelFactory.create() }, dialogFactory = dialogFactory, modifier = modifier, ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt index 672b8a703e2b..dbe75382556f 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenContent.kt @@ -50,7 +50,7 @@ class LockscreenContent( fun SceneScope.Content( modifier: Modifier = Modifier, ) { - val viewModel = rememberViewModel { viewModelFactory.create() } + val viewModel = rememberViewModel("LockscreenContent") { viewModelFactory.create() } val isContentVisible: Boolean by viewModel.isContentVisible.collectAsStateWithLifecycle() if (!isContentVisible) { // If the content isn't supposed to be visible, show a large empty box as it's needed diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt index 5f4dc6e77c63..18e1092fba2e 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt @@ -83,7 +83,7 @@ constructor( fun SceneScope.HeadsUpNotifications() { SnoozeableHeadsUpNotificationSpace( stackScrollView = stackScrollView.get(), - viewModel = rememberViewModel { viewModelFactory.create() }, + viewModel = rememberViewModel("HeadsUpNotifications") { viewModelFactory.create() }, ) } @@ -107,7 +107,7 @@ constructor( ConstrainedNotificationStack( stackScrollView = stackScrollView.get(), - viewModel = rememberViewModel { viewModelFactory.create() }, + viewModel = rememberViewModel("Notifications") { viewModelFactory.create() }, modifier = modifier .fillMaxWidth() diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt index 62213bd22cbd..e9c96eaafc74 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt @@ -81,9 +81,10 @@ constructor( override fun SceneScope.Content( modifier: Modifier, ) { - val notificationsPlaceholderViewModel = rememberViewModel { - notificationsPlaceholderViewModelFactory.create() - } + val notificationsPlaceholderViewModel = + rememberViewModel("NotificationsShadeScene") { + notificationsPlaceholderViewModelFactory.create() + } OverlayShade( modifier = modifier, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index f11f8bb94a52..d372577142c1 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -152,7 +152,9 @@ constructor( notificationStackScrollView = notificationStackScrollView.get(), viewModelFactory = contentViewModelFactory, notificationsPlaceholderViewModel = - rememberViewModel { notificationsPlaceholderViewModelFactory.create() }, + rememberViewModel("QuickSettingsScene-notifPlaceholderViewModel") { + notificationsPlaceholderViewModelFactory.create() + }, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, @@ -179,10 +181,11 @@ private fun SceneScope.QuickSettingsScene( ) { val cutoutLocation = LocalDisplayCutout.current.location - val viewModel = rememberViewModel { viewModelFactory.create() } - val brightnessMirrorViewModel = rememberViewModel { - viewModel.brightnessMirrorViewModelFactory.create() - } + val viewModel = rememberViewModel("QuickSettingsScene-viewModel") { viewModelFactory.create() } + val brightnessMirrorViewModel = + rememberViewModel("QuickSettingsScene-brightnessMirrorViewModel") { + viewModel.brightnessMirrorViewModelFactory.create() + } val brightnessMirrorShowing by brightnessMirrorViewModel.isShowing.collectAsStateWithLifecycle() val contentAlpha by animateFloatAsState( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt index b25773b68471..90d7da65b29f 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt @@ -94,7 +94,8 @@ constructor( override fun SceneScope.Content( modifier: Modifier, ) { - val viewModel = rememberViewModel { contentViewModelFactory.create() } + val viewModel = + rememberViewModel("QuickSettingsShadeScene") { contentViewModelFactory.create() } OverlayShade( viewModelFactory = viewModel.overlayShadeViewModelFactory, lockscreenContent = lockscreenContent, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt index d489d731b5fb..cbbace47ecc4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt @@ -75,7 +75,10 @@ constructor( Spacer(modifier.fillMaxSize()) SnoozeableHeadsUpNotificationSpace( stackScrollView = notificationStackScrolLView.get(), - viewModel = rememberViewModel { notificationsPlaceholderViewModelFactory.create() }, + viewModel = + rememberViewModel("GoneScene") { + notificationsPlaceholderViewModelFactory.create() + }, ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt index 445ffcb0c60c..595bbb035f21 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt @@ -69,7 +69,7 @@ fun SceneScope.OverlayShade( modifier: Modifier = Modifier, content: @Composable () -> Unit, ) { - val viewModel = rememberViewModel { viewModelFactory.create() } + val viewModel = rememberViewModel("OverlayShade") { viewModelFactory.create() } val backgroundScene by viewModel.backgroundScene.collectAsStateWithLifecycle() Box(modifier) { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt index 8c53740ebfd0..05a0119d68e4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt @@ -129,7 +129,7 @@ fun SceneScope.CollapsedShadeHeader( statusBarIconController: StatusBarIconController, modifier: Modifier = Modifier, ) { - val viewModel = rememberViewModel { viewModelFactory.create() } + val viewModel = rememberViewModel("CollapsedShadeHeader") { viewModelFactory.create() } val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() if (isDisabled) { return @@ -287,7 +287,7 @@ fun SceneScope.ExpandedShadeHeader( statusBarIconController: StatusBarIconController, modifier: Modifier = Modifier, ) { - val viewModel = rememberViewModel { viewModelFactory.create() } + val viewModel = rememberViewModel("ExpandedShadeHeader") { viewModelFactory.create() } val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() if (isDisabled) { return diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index f8513a8c4dd4..b7c6edce12d7 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -182,9 +182,12 @@ constructor( ) = ShadeScene( notificationStackScrollView.get(), - viewModel = rememberViewModel { contentViewModelFactory.create() }, + viewModel = + rememberViewModel("ShadeScene-viewModel") { contentViewModelFactory.create() }, notificationsPlaceholderViewModel = - rememberViewModel { notificationsPlaceholderViewModelFactory.create() }, + rememberViewModel("ShadeScene-notifPlaceholderViewModel") { + notificationsPlaceholderViewModelFactory.create() + }, createTintedIconManager = tintedIconManagerFactory::create, createBatteryMeterViewController = batteryMeterViewControllerFactory::create, statusBarIconController = statusBarIconController, @@ -493,9 +496,10 @@ private fun SceneScope.SplitShade( } } - val brightnessMirrorViewModel = rememberViewModel { - viewModel.brightnessMirrorViewModelFactory.create() - } + val brightnessMirrorViewModel = + rememberViewModel("SplitShade-brightnessMirrorViewModel") { + viewModel.brightnessMirrorViewModelFactory.create() + } val brightnessMirrorShowing by brightnessMirrorViewModel.isShowing.collectAsStateWithLifecycle() val contentAlpha by animateFloatAsState( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/HydratorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/HydratorTest.kt index 8c9c527bd6fd..ec6045ca0a68 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/HydratorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/HydratorTest.kt @@ -48,12 +48,13 @@ class HydratorTest : SysuiTestCase() { composeRule.setContent { val keepAlive by keepAliveMutable if (keepAlive) { - val viewModel = rememberViewModel { - FakeSysUiViewModel( - upstreamFlow = upstreamFlow, - upstreamStateFlow = upstreamStateFlow, - ) - } + val viewModel = + rememberViewModel("test") { + FakeSysUiViewModel( + upstreamFlow = upstreamFlow, + upstreamStateFlow = upstreamStateFlow, + ) + } Column { Text( diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt index c1f7d590d08e..102ae7abb3e2 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt @@ -52,7 +52,9 @@ object ComposeBouncerViewBinder { setContent { PlatformTheme { BouncerContent( - rememberViewModel { viewModelFactory.create() }, + rememberViewModel("ComposeBouncerViewBinder") { + viewModelFactory.create() + }, dialogFactory, ) } diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt index bd3d40b114e3..c1768a4d903c 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/Activatable.kt @@ -19,6 +19,7 @@ package com.android.systemui.lifecycle import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember +import com.android.app.tracing.coroutines.traceCoroutine /** Defines interface for classes that can be activated to do coroutine work. */ interface Activatable { @@ -66,13 +67,19 @@ interface Activatable { * * If the [key] changes, the old [Activatable] is deactivated and a new one will be instantiated, * activated, and returned. + * + * The [traceName] is used for coroutine performance tracing purposes. Please try to use a label + * that's unique enough and easy enough to find in code search; this should help correlate + * performance findings with actual code. One recommendation: prefer whole string literals instead + * of some complex concatenation or templating scheme. */ @Composable fun <T : Activatable> rememberActivated( + traceName: String, key: Any = Unit, factory: () -> T, ): T { val instance = remember(key) { factory() } - LaunchedEffect(instance) { instance.activate() } + LaunchedEffect(instance) { traceCoroutine(traceName) { instance.activate() } } return instance } diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt index 29ffcbd15125..e90586c94e1b 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt @@ -20,6 +20,7 @@ import android.view.View import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember +import com.android.app.tracing.coroutines.traceCoroutine import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -31,15 +32,21 @@ interface SysUiViewModel * [Activatable], it's automatically kept active until this composable leaves the composition; if * the [key] changes, the old [SysUiViewModel] is deactivated and a new one will be instantiated, * activated, and returned. + * + * The [traceName] is used for coroutine performance tracing purposes. Please try to use a label + * that's unique enough and easy enough to find in code search; this should help correlate + * performance findings with actual code. One recommendation: prefer whole string literals instead + * of some complex concatenation or templating scheme. */ @Composable fun <T : SysUiViewModel> rememberViewModel( + traceName: String, key: Any = Unit, factory: () -> T, ): T { val instance = remember(key) { factory() } if (instance is Activatable) { - LaunchedEffect(instance) { instance.activate() } + LaunchedEffect(instance) { traceCoroutine(traceName) { instance.activate() } } } return instance } @@ -48,8 +55,14 @@ fun <T : SysUiViewModel> rememberViewModel( * Invokes [block] in a new coroutine with a new [SysUiViewModel] that is automatically activated * whenever `this` [View]'s Window's [WindowLifecycleState] is at least at * [minWindowLifecycleState], and is automatically canceled once that is no longer the case. + * + * The [traceName] is used for coroutine performance tracing purposes. Please try to use a label + * that's unique enough and easy enough to find in code search; this should help correlate + * performance findings with actual code. One recommendation: prefer whole string literals instead + * of some complex concatenation or templating scheme. */ suspend fun <T : SysUiViewModel> View.viewModel( + traceName: String, minWindowLifecycleState: WindowLifecycleState, factory: () -> T, block: suspend CoroutineScope.(T) -> Unit, @@ -57,7 +70,7 @@ suspend fun <T : SysUiViewModel> View.viewModel( repeatOnWindowLifecycle(minWindowLifecycleState) { val instance = factory() if (instance is Activatable) { - launch { instance.activate() } + launch { traceCoroutine(traceName) { instance.activate() } } } block(instance) } diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt index b870a4e0b5e3..ec6513a99cad 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt @@ -104,6 +104,7 @@ object SceneWindowRootViewBinder { view.repeatWhenAttached { view.viewModel( + traceName = "SceneWindowRootViewBinder", minWindowLifecycleState = WindowLifecycleState.ATTACHED, factory = { viewModelFactory.create(motionEventHandlerReceiver) }, ) { viewModel -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt index 3cc6e81986c5..6d5553fec6b4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt @@ -67,6 +67,7 @@ constructor( suspend fun bind(): Nothing = view.asView().viewModel( + traceName = "NotificationScrollViewBinder", minWindowLifecycleState = WindowLifecycleState.ATTACHED, factory = viewModelFactory::create, ) { viewModel -> diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt index 8e215f994e4d..fd550b05fdc9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerContentTest.kt @@ -83,7 +83,9 @@ class BouncerContentTest : SysuiTestCase() { PlatformTheme { BouncerContent( viewModel = - rememberViewModel { kosmos.bouncerSceneContentViewModelFactory.create() }, + rememberViewModel("test") { + kosmos.bouncerSceneContentViewModelFactory.create() + }, layout = BouncerSceneLayout.BESIDE_USER_SWITCHER, modifier = Modifier.fillMaxSize().testTag("BouncerContent"), dialogFactory = bouncerDialogFactory diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/ActivatableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/ActivatableTest.kt index 67517a25ec87..2ba670ceb76a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/ActivatableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/ActivatableTest.kt @@ -40,7 +40,7 @@ class ActivatableTest : SysuiTestCase() { composeRule.setContent { val keepAlive by keepAliveMutable if (keepAlive) { - rememberActivated { + rememberActivated("test") { FakeActivatable( onActivation = { isActive = true }, onDeactivation = { isActive = false }, @@ -58,7 +58,7 @@ class ActivatableTest : SysuiTestCase() { composeRule.setContent { val keepAlive by keepAliveMutable if (keepAlive) { - rememberActivated { + rememberActivated("name") { FakeActivatable( onActivation = { isActive = true }, onDeactivation = { isActive = false }, diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt index c7acd78c5623..9a7df6e25665 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/SysUiViewModelTest.kt @@ -51,7 +51,7 @@ class SysUiViewModelTest : SysuiTestCase() { composeRule.setContent { val keepAlive by keepAliveMutable if (keepAlive) { - rememberViewModel { + rememberViewModel("test") { FakeSysUiViewModel( onActivation = { isActive = true }, onDeactivation = { isActive = false }, @@ -69,21 +69,25 @@ class SysUiViewModelTest : SysuiTestCase() { var isActive2 = false composeRule.setContent { val key by keyMutable - rememberViewModel(key) { - when (key) { - 1 -> - FakeSysUiViewModel( - onActivation = { isActive1 = true }, - onDeactivation = { isActive1 = false }, - ) - 2 -> - FakeSysUiViewModel( - onActivation = { isActive2 = true }, - onDeactivation = { isActive2 = false }, - ) - else -> error("unsupported key $key") + // Need to explicitly state the type to avoid a weird issue where the factory seems to + // return Unit instead of FakeSysUiViewModel. It might be an issue with the compose + // compiler. + val unused: FakeSysUiViewModel = + rememberViewModel("test", key) { + when (key) { + 1 -> + FakeSysUiViewModel( + onActivation = { isActive1 = true }, + onDeactivation = { isActive1 = false }, + ) + 2 -> + FakeSysUiViewModel( + onActivation = { isActive2 = true }, + onDeactivation = { isActive2 = false }, + ) + else -> error("unsupported key $key") + } } - } } assertThat(isActive1).isTrue() assertThat(isActive2).isFalse() @@ -106,7 +110,7 @@ class SysUiViewModelTest : SysuiTestCase() { composeRule.setContent { val keepAlive by keepAliveMutable if (keepAlive) { - rememberViewModel { + rememberViewModel("test") { FakeSysUiViewModel( onActivation = { isActive = true }, onDeactivation = { isActive = false }, @@ -130,6 +134,7 @@ class SysUiViewModelTest : SysuiTestCase() { val viewModel = FakeViewModel() backgroundScope.launch { view.viewModel( + traceName = "test", minWindowLifecycleState = WindowLifecycleState.ATTACHED, factory = { viewModel }, ) { |