Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bc2192f authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Reapply "Cache the movable content used for Status icons"

This reverts commit 019e3eb61b86b5f1b6edbe526f2cf78267536578.

Address the issue in DesktopStatusBar by not checking
LocalStatusIconContext in the shared code. Instead, we pass the
AndroidView content.

It's a movable content, so the AndroidView will not be recreated every
time tint changes.

Test: manual, check DesktopStatusBar works correctly
Test: desktop presubmit
Flag: com.android.systemui.scene_container
Flag: com.android.systemui.status_bar_for_desktop
Fixes: 430728918

Change-Id: Ie60c18067967381344ec752f7f6d8a803fd99b02
parent 231baae5
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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
@@ -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!") }

@@ -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) {
@@ -84,6 +95,14 @@ fun WithStatusIconContext(
                        )
                    }
                }

                override fun movableContent(
                    tintedIconManager: TintedIconManager
                ): MovableSystemStatusIconLegacy {
                    return movableContentByIconManager.getOrPut(tintedIconManager) {
                        movableSystemStatusIconsLegacyAndroidView(tintedIconManager)
                    }
                }
            }
        }

+3 −0
Original line number Diff line number Diff line
@@ -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) {
@@ -746,6 +748,7 @@ private fun ContentScope.StatusIcons(
            isPrivacyChipEnabled = viewModel.isPrivacyChipVisible,
            isLocationIndicationEnabled = viewModel.isLocationIndicationEnabled,
            modifier = modifier,
            content = movableContent,
        )
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -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 {
@@ -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) },
@@ -243,6 +247,7 @@ private fun QuickSettingsChip(
                    isPrivacyChipEnabled = true,
                    isTransitioning = false,
                    isLocationIndicationEnabled = true,
                    content = movableContent,
                )
            }
        }
+104 −26
Original line number Diff line number Diff line
@@ -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
@@ -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,
@@ -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(
@@ -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) {
@@ -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,
    )
}