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

Commit 1c75a364 authored by Ahmed Mehfooz's avatar Ahmed Mehfooz Committed by Android (Google) Code Review
Browse files

Merge changes I8a6b3e86,I093c53cb into main

* changes:
  [SB][ComposeIcons] Move legacy SystemStatusIcons
  [SB][ComposableIcons] Use composable status icons in ShadeHeader
parents 9ecb8db6 ec1aafc4
Loading
Loading
Loading
Loading
+33 −56
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@ import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
@@ -101,6 +100,9 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierG
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModelKairos
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.composeWrapper
import com.android.systemui.statusbar.policy.Clock
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.util.composable.kairos.ActivatedKairosSpec
import kotlin.math.max
import kotlin.math.roundToInt
@@ -717,67 +719,42 @@ private fun ContentScope.StatusIcons(
    val inverseColor =
        Utils.getColorAttrDefaultColor(themedContext, android.R.attr.textColorPrimaryInverse)

    val carrierIconSlots =
        listOf(
            stringResource(id = com.android.internal.R.string.status_bar_mobile),
            stringResource(id = com.android.internal.R.string.status_bar_stacked_mobile),
        )
    val cameraSlot = stringResource(id = com.android.internal.R.string.status_bar_camera)
    val micSlot = stringResource(id = com.android.internal.R.string.status_bar_microphone)
    val locationSlot = stringResource(id = com.android.internal.R.string.status_bar_location)

    val statusIconContext = LocalStatusIconContext.current
    val iconContainer = statusIconContext.iconContainer(contentKey)
    val iconManager = statusIconContext.iconManager(contentKey)

    // TODO(408001821): Use composable system status icons here instead.
    AndroidView(
        factory = {
            iconManager.setTint(primaryColor, inverseColor)
            viewModel.statusBarIconController.addIconGroup(iconManager)

            iconContainer
        },
        onRelease = { viewModel.statusBarIconController.removeIconGroup(iconManager) },
        update = { iconContainer ->
            iconContainer.setQsExpansionTransitioning(
                layoutState.isTransitioningBetween(Scenes.Shade, Scenes.QuickSettings)
            )
            if (viewModel.isSingleCarrier || !useExpandedFormat) {
                iconContainer.removeIgnoredSlots(carrierIconSlots)
            } else {
                iconContainer.addIgnoredSlots(carrierIconSlots)
            }

            if (viewModel.isPrivacyChipEnabled) {
                if (viewModel.isMicCameraIndicationEnabled) {
                    iconContainer.addIgnoredSlot(cameraSlot)
                    iconContainer.addIgnoredSlot(micSlot)
                } else {
                    iconContainer.removeIgnoredSlot(cameraSlot)
                    iconContainer.removeIgnoredSlot(micSlot)
                }
                if (viewModel.isLocationIndicationEnabled) {
                    iconContainer.addIgnoredSlot(locationSlot)
                } else {
                    iconContainer.removeIgnoredSlot(locationSlot)
                }
            } else {
                iconContainer.removeIgnoredSlot(cameraSlot)
                iconContainer.removeIgnoredSlot(micSlot)
                iconContainer.removeIgnoredSlot(locationSlot)
            }

            // TODO(b/397223606): Get the actual spec for this.
    // TODO(408001821): Add support for background color like [TintedIconManager.setTint].
    if (SystemStatusIconsInCompose.isEnabled) {
        SystemStatusIcons(
            viewModelFactory = viewModel.systemStatusIconsViewModelFactory,
            tint =
                if (isHighlighted) {
                iconManager.setTint(inverseColor, primaryColor)
                    Color(inverseColor)
                } else {
                iconManager.setTint(primaryColor, inverseColor)
            }
                    Color(primaryColor)
                },
        )
    } else {
        val foregroundColor = if (isHighlighted) inverseColor else primaryColor
        val backgroundColor = if (isHighlighted) primaryColor else inverseColor
        val isTransitioning = layoutState.isTransitioningBetween(Scenes.Shade, Scenes.QuickSettings)

        SystemStatusIconsLegacy(
            iconContainer = iconContainer,
            iconManager = iconManager,
            statusBarIconController = viewModel.statusBarIconController,
            useExpandedFormat = useExpandedFormat,
            isTransitioning = isTransitioning,
            foregroundColor = foregroundColor,
            backgroundColor = backgroundColor,
            isSingleCarrier = viewModel.isSingleCarrier,
            isMicCameraIndicationEnabled = viewModel.isMicCameraIndicationEnabled,
            isPrivacyChipEnabled = viewModel.isPrivacyChipVisible,
            isLocationIndicationEnabled = viewModel.isLocationIndicationEnabled,
            modifier = modifier,
        )
    }
}

@Composable
private fun ContentScope.PrivacyChip(
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.pipeline.battery.ui.viewmodel.BatteryViewM
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModelKairos
import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatusIconsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -77,6 +78,7 @@ constructor(
    private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
    val statusBarIconController: StatusBarIconController,
    val batteryViewModelFactory: BatteryViewModel.AlwaysShowPercent.Factory,
    val systemStatusIconsViewModelFactory: SystemStatusIconsViewModel.Factory,
    val kairosNetwork: KairosNetwork,
    val mobileIconsViewModelKairos: dagger.Lazy<MobileIconsViewModelKairos>,
    private val dualShadeEducationInteractor: DualShadeEducationInteractor,
+27 −1
Original line number Diff line number Diff line
@@ -31,11 +31,16 @@ import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onLayoutRectChanged
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
@@ -81,6 +86,7 @@ import com.android.systemui.statusbar.phone.NotificationIconContainer
import com.android.systemui.statusbar.phone.PhoneStatusBarView
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController
import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
import com.android.systemui.statusbar.phone.ui.DarkIconManager
@@ -98,6 +104,7 @@ import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBar
import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.systemstatusicons.SystemStatusIconsInCompose
import com.android.systemui.statusbar.systemstatusicons.ui.compose.SystemStatusIcons
import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatusIconsViewModel
import com.android.systemui.statusbar.ui.viewmodel.StatusBarRegionSamplingViewModel
import javax.inject.Inject
import javax.inject.Named
@@ -551,7 +558,7 @@ private fun addSystemStatusIconsComposable(
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(6.dp),
                ) {
                    SystemStatusIcons(
                    SystemStatusIconsContainer(
                        viewModelFactory = statusBarViewModel.systemStatusIconsViewModelFactory,
                        isDark = statusBarViewModel.areaDark,
                    )
@@ -589,6 +596,25 @@ private fun addSystemStatusIconsComposable(
    }
}

@Composable
private fun SystemStatusIconsContainer(
    viewModelFactory: SystemStatusIconsViewModel.Factory,
    isDark: IsAreaDark,
    modifier: Modifier = Modifier,
) {
    var bounds by remember { mutableStateOf(Rect()) }
    val tint = if (isDark.isDarkTheme(bounds)) Color.White else Color.Black
    SystemStatusIcons(
        viewModelFactory = viewModelFactory,
        tint = tint,
        modifier =
            modifier.onLayoutRectChanged { relativeLayoutBounds ->
                bounds =
                    with(relativeLayoutBounds.boundsInScreen) { Rect(left, top, right, bottom) }
            },
    )
}

private fun bindRegionSamplingViewModel(
    displayId: Int,
    phoneStatusBarView: PhoneStatusBarView,
+25 −40
Original line number Diff line number Diff line
@@ -16,27 +16,20 @@

package com.android.systemui.statusbar.systemstatusicons.ui.compose

import android.graphics.Rect
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onLayoutRectChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.statusbar.phone.domain.interactor.IsAreaDark
import com.android.systemui.statusbar.pipeline.mobile.ui.compose.MobileIcons
import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatusIconViewModel
import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatusIconsViewModel
@@ -48,24 +41,17 @@ import com.android.systemui.statusbar.systemstatusicons.ui.viewmodel.SystemStatu
@Composable
fun SystemStatusIcons(
    viewModelFactory: SystemStatusIconsViewModel.Factory,
    isDark: IsAreaDark,
    tint: Color,
    modifier: Modifier = Modifier,
) {
    val context = LocalContext.current
    var bounds by remember { mutableStateOf(Rect()) }
    val color = if (isDark.isDarkTheme(bounds)) Color.White else Color.Black
    CompositionLocalProvider(LocalContentColor provides color) {
    val viewModel =
        rememberViewModel(traceName = "SystemStatusIcons") { viewModelFactory.create(context) }

    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(6.dp),
            modifier =
                modifier.onLayoutRectChanged { relativeLayoutBounds ->
                    bounds =
                        with(relativeLayoutBounds.boundsInScreen) { Rect(left, top, right, bottom) }
                },
        modifier = modifier,
    ) {
        viewModel.iconViewModels
            .filter { it.visible }
@@ -77,7 +63,7 @@ fun SystemStatusIcons(
                            Icon(
                                icon = it,
                                modifier = Modifier.size(20.dp).padding(1.dp),
                                    tint = LocalContentColor.current,
                                tint = tint,
                            )
                        }
                    is SystemStatusIconViewModel.MobileIcons -> {
@@ -90,4 +76,3 @@ fun SystemStatusIcons(
            }
    }
}
}
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.systemstatusicons.ui.compose

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager

@Composable
fun SystemStatusIconsLegacy(
    statusBarIconController: StatusBarIconController,
    iconContainer: StatusIconContainer,
    iconManager: TintedIconManager,
    useExpandedFormat: Boolean,
    isTransitioning: Boolean,
    foregroundColor: Int,
    backgroundColor: Int,
    isSingleCarrier: Boolean,
    isMicCameraIndicationEnabled: Boolean,
    isPrivacyChipEnabled: Boolean,
    isLocationIndicationEnabled: Boolean,
    modifier: Modifier = Modifier,
) {
    val carrierIconSlots =
        listOf(
            stringResource(id = com.android.internal.R.string.status_bar_mobile),
            stringResource(id = com.android.internal.R.string.status_bar_stacked_mobile),
        )
    val cameraSlot = stringResource(id = com.android.internal.R.string.status_bar_camera)
    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 ->
            container.setQsExpansionTransitioning(isTransitioning)

            if (isSingleCarrier || !useExpandedFormat) {
                container.removeIgnoredSlots(carrierIconSlots)
            } else {
                container.addIgnoredSlots(carrierIconSlots)
            }

            if (isPrivacyChipEnabled) {
                if (isMicCameraIndicationEnabled) {
                    container.addIgnoredSlot(cameraSlot)
                    container.addIgnoredSlot(micSlot)
                } else {
                    container.removeIgnoredSlot(cameraSlot)
                    container.removeIgnoredSlot(micSlot)
                }
                if (isLocationIndicationEnabled) {
                    container.addIgnoredSlot(locationSlot)
                } else {
                    container.removeIgnoredSlot(locationSlot)
                }
            } else {
                container.removeIgnoredSlot(cameraSlot)
                container.removeIgnoredSlot(micSlot)
                container.removeIgnoredSlot(locationSlot)
            }

            iconManager.setTint(foregroundColor, backgroundColor)
        },
        modifier = modifier,
    )
}
Loading