Loading packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/LocalStatusIconContext.kt +19 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.statusbar.phone.ui.TintedIconManager import com.android.systemui.statusbar.systemstatusicons.ui.compose.MovableSystemStatusIconLegacy import com.android.systemui.statusbar.systemstatusicons.ui.compose.movableSystemStatusIconsLegacyAndroidView /** * Defines interface for classes that can provide a context for UI that renders the status bar Loading @@ -45,8 +47,15 @@ interface StatusIconContext { * cached in the [StatusIconContext]. */ fun iconManager(contentKey: ContentKey): TintedIconManager /** * Returns a [MovableSystemStatusIconLegacy] movable content for the given [TintedIconManager]. * This movable content will be cached in the [StatusIconContext]. */ fun movableContent(tintedIconManager: TintedIconManager): MovableSystemStatusIconLegacy } /** This is only set inside the SceneContainer STL. */ val LocalStatusIconContext = compositionLocalOf<StatusIconContext> { error("LocalStatusIconContext not set!") } Loading @@ -63,6 +72,8 @@ fun WithStatusIconContext( private val iconContainerByContentKey = mutableMapOf<ContentKey, StatusIconContainer>() private val iconManagerByContentKey = mutableMapOf<ContentKey, TintedIconManager>() private val movableContentByIconManager = mutableMapOf<TintedIconManager, MovableSystemStatusIconLegacy>() override fun iconContainer(contentKey: ContentKey): StatusIconContainer { return iconContainerByContentKey.getOrPut(contentKey) { Loading @@ -84,6 +95,14 @@ fun WithStatusIconContext( ) } } override fun movableContent( tintedIconManager: TintedIconManager ): MovableSystemStatusIconLegacy { return movableContentByIconManager.getOrPut(tintedIconManager) { movableSystemStatusIconsLegacyAndroidView(tintedIconManager) } } } } Loading packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +3 −0 Original line number Diff line number Diff line Loading @@ -723,6 +723,8 @@ private fun ContentScope.StatusIcons( val statusIconContext = LocalStatusIconContext.current val iconContainer = statusIconContext.iconContainer(contentKey) val iconManager = statusIconContext.iconManager(contentKey) val movableContent = remember(statusIconContext, iconManager) { statusIconContext.movableContent(iconManager) } // TODO(408001821): Add support for background color like [TintedIconManager.setTint]. if (SystemStatusIconsInCompose.isEnabled) { Loading @@ -746,6 +748,7 @@ private fun ContentScope.StatusIcons( isPrivacyChipEnabled = viewModel.isPrivacyChipVisible, isLocationIndicationEnabled = viewModel.isLocationIndicationEnabled, modifier = modifier, content = movableContent, ) } } Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/DesktopStatusBar.kt +5 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBar import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose import com.android.systemui.statusbar.systemstatusicons.ui.compose.SystemStatusIcons import com.android.systemui.statusbar.systemstatusicons.ui.compose.SystemStatusIconsLegacy import com.android.systemui.statusbar.systemstatusicons.ui.compose.movableSystemStatusIconsLegacyAndroidView object DesktopStatusBar { object Dimensions { Loading Loading @@ -227,6 +228,9 @@ private fun QuickSettingsChip( iconManagerFactory.create(iconContainer, StatusBarLocation.HOME) } val movableContent = remember(iconManager) { movableSystemStatusIconsLegacyAndroidView(iconManager) } WithAdaptiveTint( isHighlighted = viewModel.isQuickSettingsChipHighlighted, isDarkProvider = { bounds -> viewModel.areaDark.isDarkTheme(bounds) }, Loading @@ -243,6 +247,7 @@ private fun QuickSettingsChip( isPrivacyChipEnabled = true, isTransitioning = false, isLocationIndicationEnabled = true, content = movableContent, ) } } Loading packages/SystemUI/src/com/android/systemui/statusbar/systemstatusicons/ui/compose/SystemStatusIconsLegacy.kt +104 −26 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ package com.android.systemui.statusbar.systemstatusicons.ui.compose import androidx.compose.runtime.Composable import androidx.compose.runtime.annotation.RememberInComposition import androidx.compose.runtime.getValue import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.viewinterop.AndroidView Loading @@ -24,6 +29,7 @@ import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager @Suppress("NAME_SHADOWING") @Composable fun SystemStatusIconsLegacy( statusBarIconController: StatusBarIconController, Loading @@ -38,6 +44,13 @@ fun SystemStatusIconsLegacy( isPrivacyChipEnabled: Boolean, isLocationIndicationEnabled: Boolean, modifier: Modifier = Modifier, /** * This content should call through to [SystemStatusIconsLegacyAndroidView]. One way is to * provide it using [movableSystemStatusIconsLegacyAndroidView]. If remembered tied to the * [TintedIconManager], it will be re-used and avoid issues of re-using the same * [TintedIconManager]. */ content: MovableSystemStatusIconLegacy, ) { val carrierIconSlots = listOf( Loading @@ -48,13 +61,29 @@ fun SystemStatusIconsLegacy( val micSlot = stringResource(id = com.android.internal.R.string.status_bar_microphone) val locationSlot = stringResource(id = com.android.internal.R.string.status_bar_location) AndroidView( factory = { statusBarIconController.addIconGroup(iconManager) iconContainer }, onRelease = { statusBarIconController.removeIconGroup(iconManager) }, update = { container -> /* * Use `rememberUpdatedState` to guarantee that a state will be exposed (without recomposition) * for all these parameters, so the update block will be called when any of them changes. */ val useExpandedFormat by rememberUpdatedState(useExpandedFormat) val isTransitioning by rememberUpdatedState(isTransitioning) val foregroundColor by rememberUpdatedState(foregroundColor) val backgroundColor by rememberUpdatedState(backgroundColor) val isSingleCarrier by rememberUpdatedState(isSingleCarrier) val isMicCameraIndicationEnabled by rememberUpdatedState(isMicCameraIndicationEnabled) val isPrivacyChipEnabled by rememberUpdatedState(isPrivacyChipEnabled) val isLocationIndicationEnabled by rememberUpdatedState(isLocationIndicationEnabled) val update = remember( statusBarIconController, iconManager, carrierIconSlots, cameraSlot, micSlot, locationSlot, ) { { container: StatusIconContainer -> container.setQsExpansionTransitioning(isTransitioning) if (isSingleCarrier || !useExpandedFormat) { Loading Loading @@ -83,7 +112,56 @@ fun SystemStatusIconsLegacy( } iconManager.setTint(foregroundColor, backgroundColor) } } content(statusBarIconController, iconContainer, update, modifier) } /** Alias for [movableSystemStatusIconsLegacyAndroidView] */ typealias MovableSystemStatusIconLegacy = @Composable (StatusBarIconController, StatusIconContainer, (StatusIconContainer) -> Unit, Modifier) -> Unit /** * Returns a movable content for the given `TintedIconManager`. This can be used to guarantee that * the same one is always used (to prevent double registration with [StatusBarIconController]) when * used with a cache. */ @RememberInComposition fun movableSystemStatusIconsLegacyAndroidView( iconManager: TintedIconManager ): MovableSystemStatusIconLegacy { return movableContentOf { statusBarIconController: StatusBarIconController, iconContainer: StatusIconContainer, update: (StatusIconContainer) -> Unit, modifier: Modifier -> SystemStatusIconsLegacyAndroidView( statusBarIconController, iconManager, iconContainer, update, modifier, ) } } @Composable private fun SystemStatusIconsLegacyAndroidView( statusBarIconController: StatusBarIconController, iconManager: TintedIconManager, iconContainer: StatusIconContainer, update: (StatusIconContainer) -> Unit, modifier: Modifier = Modifier, ) { AndroidView( factory = { statusBarIconController.addIconGroup(iconManager) iconContainer }, onRelease = { statusBarIconController.removeIconGroup(iconManager) }, update = update, modifier = modifier, ) } Loading
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/LocalStatusIconContext.kt +19 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.phone.StatusBarLocation import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.statusbar.phone.ui.TintedIconManager import com.android.systemui.statusbar.systemstatusicons.ui.compose.MovableSystemStatusIconLegacy import com.android.systemui.statusbar.systemstatusicons.ui.compose.movableSystemStatusIconsLegacyAndroidView /** * Defines interface for classes that can provide a context for UI that renders the status bar Loading @@ -45,8 +47,15 @@ interface StatusIconContext { * cached in the [StatusIconContext]. */ fun iconManager(contentKey: ContentKey): TintedIconManager /** * Returns a [MovableSystemStatusIconLegacy] movable content for the given [TintedIconManager]. * This movable content will be cached in the [StatusIconContext]. */ fun movableContent(tintedIconManager: TintedIconManager): MovableSystemStatusIconLegacy } /** This is only set inside the SceneContainer STL. */ val LocalStatusIconContext = compositionLocalOf<StatusIconContext> { error("LocalStatusIconContext not set!") } Loading @@ -63,6 +72,8 @@ fun WithStatusIconContext( private val iconContainerByContentKey = mutableMapOf<ContentKey, StatusIconContainer>() private val iconManagerByContentKey = mutableMapOf<ContentKey, TintedIconManager>() private val movableContentByIconManager = mutableMapOf<TintedIconManager, MovableSystemStatusIconLegacy>() override fun iconContainer(contentKey: ContentKey): StatusIconContainer { return iconContainerByContentKey.getOrPut(contentKey) { Loading @@ -84,6 +95,14 @@ fun WithStatusIconContext( ) } } override fun movableContent( tintedIconManager: TintedIconManager ): MovableSystemStatusIconLegacy { return movableContentByIconManager.getOrPut(tintedIconManager) { movableSystemStatusIconsLegacyAndroidView(tintedIconManager) } } } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +3 −0 Original line number Diff line number Diff line Loading @@ -723,6 +723,8 @@ private fun ContentScope.StatusIcons( val statusIconContext = LocalStatusIconContext.current val iconContainer = statusIconContext.iconContainer(contentKey) val iconManager = statusIconContext.iconManager(contentKey) val movableContent = remember(statusIconContext, iconManager) { statusIconContext.movableContent(iconManager) } // TODO(408001821): Add support for background color like [TintedIconManager.setTint]. if (SystemStatusIconsInCompose.isEnabled) { Loading @@ -746,6 +748,7 @@ private fun ContentScope.StatusIcons( isPrivacyChipEnabled = viewModel.isPrivacyChipVisible, isLocationIndicationEnabled = viewModel.isLocationIndicationEnabled, modifier = modifier, content = movableContent, ) } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/DesktopStatusBar.kt +5 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBar import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose import com.android.systemui.statusbar.systemstatusicons.ui.compose.SystemStatusIcons import com.android.systemui.statusbar.systemstatusicons.ui.compose.SystemStatusIconsLegacy import com.android.systemui.statusbar.systemstatusicons.ui.compose.movableSystemStatusIconsLegacyAndroidView object DesktopStatusBar { object Dimensions { Loading Loading @@ -227,6 +228,9 @@ private fun QuickSettingsChip( iconManagerFactory.create(iconContainer, StatusBarLocation.HOME) } val movableContent = remember(iconManager) { movableSystemStatusIconsLegacyAndroidView(iconManager) } WithAdaptiveTint( isHighlighted = viewModel.isQuickSettingsChipHighlighted, isDarkProvider = { bounds -> viewModel.areaDark.isDarkTheme(bounds) }, Loading @@ -243,6 +247,7 @@ private fun QuickSettingsChip( isPrivacyChipEnabled = true, isTransitioning = false, isLocationIndicationEnabled = true, content = movableContent, ) } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/systemstatusicons/ui/compose/SystemStatusIconsLegacy.kt +104 −26 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ package com.android.systemui.statusbar.systemstatusicons.ui.compose import androidx.compose.runtime.Composable import androidx.compose.runtime.annotation.RememberInComposition import androidx.compose.runtime.getValue import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.viewinterop.AndroidView Loading @@ -24,6 +29,7 @@ import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.phone.ui.TintedIconManager @Suppress("NAME_SHADOWING") @Composable fun SystemStatusIconsLegacy( statusBarIconController: StatusBarIconController, Loading @@ -38,6 +44,13 @@ fun SystemStatusIconsLegacy( isPrivacyChipEnabled: Boolean, isLocationIndicationEnabled: Boolean, modifier: Modifier = Modifier, /** * This content should call through to [SystemStatusIconsLegacyAndroidView]. One way is to * provide it using [movableSystemStatusIconsLegacyAndroidView]. If remembered tied to the * [TintedIconManager], it will be re-used and avoid issues of re-using the same * [TintedIconManager]. */ content: MovableSystemStatusIconLegacy, ) { val carrierIconSlots = listOf( Loading @@ -48,13 +61,29 @@ fun SystemStatusIconsLegacy( val micSlot = stringResource(id = com.android.internal.R.string.status_bar_microphone) val locationSlot = stringResource(id = com.android.internal.R.string.status_bar_location) AndroidView( factory = { statusBarIconController.addIconGroup(iconManager) iconContainer }, onRelease = { statusBarIconController.removeIconGroup(iconManager) }, update = { container -> /* * Use `rememberUpdatedState` to guarantee that a state will be exposed (without recomposition) * for all these parameters, so the update block will be called when any of them changes. */ val useExpandedFormat by rememberUpdatedState(useExpandedFormat) val isTransitioning by rememberUpdatedState(isTransitioning) val foregroundColor by rememberUpdatedState(foregroundColor) val backgroundColor by rememberUpdatedState(backgroundColor) val isSingleCarrier by rememberUpdatedState(isSingleCarrier) val isMicCameraIndicationEnabled by rememberUpdatedState(isMicCameraIndicationEnabled) val isPrivacyChipEnabled by rememberUpdatedState(isPrivacyChipEnabled) val isLocationIndicationEnabled by rememberUpdatedState(isLocationIndicationEnabled) val update = remember( statusBarIconController, iconManager, carrierIconSlots, cameraSlot, micSlot, locationSlot, ) { { container: StatusIconContainer -> container.setQsExpansionTransitioning(isTransitioning) if (isSingleCarrier || !useExpandedFormat) { Loading Loading @@ -83,7 +112,56 @@ fun SystemStatusIconsLegacy( } iconManager.setTint(foregroundColor, backgroundColor) } } content(statusBarIconController, iconContainer, update, modifier) } /** Alias for [movableSystemStatusIconsLegacyAndroidView] */ typealias MovableSystemStatusIconLegacy = @Composable (StatusBarIconController, StatusIconContainer, (StatusIconContainer) -> Unit, Modifier) -> Unit /** * Returns a movable content for the given `TintedIconManager`. This can be used to guarantee that * the same one is always used (to prevent double registration with [StatusBarIconController]) when * used with a cache. */ @RememberInComposition fun movableSystemStatusIconsLegacyAndroidView( iconManager: TintedIconManager ): MovableSystemStatusIconLegacy { return movableContentOf { statusBarIconController: StatusBarIconController, iconContainer: StatusIconContainer, update: (StatusIconContainer) -> Unit, modifier: Modifier -> SystemStatusIconsLegacyAndroidView( statusBarIconController, iconManager, iconContainer, update, modifier, ) } } @Composable private fun SystemStatusIconsLegacyAndroidView( statusBarIconController: StatusBarIconController, iconManager: TintedIconManager, iconContainer: StatusIconContainer, update: (StatusIconContainer) -> Unit, modifier: Modifier = Modifier, ) { AndroidView( factory = { statusBarIconController.addIconGroup(iconManager) iconContainer }, onRelease = { statusBarIconController.removeIconGroup(iconManager) }, update = update, modifier = modifier, ) }