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

Commit 36d14c78 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "new-battery" into main

* changes:
  [Dual Shade] Refactor ShadeHeaderViewModel, removing all StateFlows.
  [flexiglass] Adjust the battery estimate text color based on the theme.
  [Dual Shade] Avoid showing the battery icon twice in QuickSettings shade
  [flexiglass] Use the new compose battery icon in the shade header.
parents 206f5458 2350d917
Loading
Loading
Loading
Loading
+66 −44
Original line number Diff line number Diff line
@@ -72,7 +72,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.LowestZIndexContentPicker
@@ -92,6 +91,7 @@ import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.kairos.ExperimentalKairosApi
import com.android.systemui.kairos.util.nameTag
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.DualShadeEducationElement
import com.android.systemui.scene.shared.model.Scenes
@@ -102,6 +102,7 @@ import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
import com.android.systemui.statusbar.core.NewStatusBarIcons
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.pipeline.battery.ui.composable.BatteryWithEstimate
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModelKairosComposeWrapper
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel
@@ -172,7 +173,7 @@ object ShadeHeader {
    }
}

/** The status bar that appears above the Shade scene on small screens */
/** The status bar that appears above the Shade scene on small screens. */
@Composable
fun ContentScope.CollapsedShadeHeader(
    viewModel: ShadeHeaderViewModel,
@@ -191,8 +192,6 @@ fun ContentScope.CollapsedShadeHeader(
            }
        }

    val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsStateWithLifecycle()

    // This layout assumes it is globally positioned at (0, 0) and is the same size as the screen.
    CutoutAwareShadeHeader(
        modifier = modifier,
@@ -212,10 +211,11 @@ fun ContentScope.CollapsedShadeHeader(
            }
        },
        endContent = {
            if (isPrivacyChipVisible) {
            if (viewModel.isPrivacyChipVisible) {
                Box(modifier = Modifier.fillMaxSize().padding(horizontal = horizontalPadding)) {
                    PrivacyChip(
                        viewModel = viewModel,
                        privacyList = viewModel.privacyItems,
                        onClick = viewModel::onPrivacyChipClicked,
                        modifier = Modifier.align(Alignment.CenterEnd),
                    )
                }
@@ -242,11 +242,12 @@ fun ContentScope.CollapsedShadeHeader(
                            useExpandedFormat = useExpandedTextFormat,
                            modifier = Modifier.padding(end = paddingEnd).weight(1f, fill = false),
                        )
                        BatteryIcon(
                            createBatteryMeterViewController =
                                viewModel.createBatteryMeterViewController,
                        BatteryInfo(
                            viewModel = viewModel,
                            showIcon = true,
                            useExpandedFormat = useExpandedTextFormat,
                            modifier = Modifier.padding(vertical = 8.dp),
                            textColor = Color.White, // Single shade is always in Dark theme
                        )
                    }
                }
@@ -255,7 +256,7 @@ fun ContentScope.CollapsedShadeHeader(
    )
}

/** The status bar that appears above the Quick Settings scene on small screens */
/** The status bar that appears above the Quick Settings scene on small screens. */
@Composable
fun ContentScope.ExpandedShadeHeader(
    viewModel: ShadeHeaderViewModel,
@@ -265,12 +266,14 @@ fun ContentScope.ExpandedShadeHeader(
        derivedStateOf { shouldUseExpandedFormat(layoutState.transitionState) }
    }

    val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsStateWithLifecycle()

    Box(modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root)) {
        if (isPrivacyChipVisible) {
        if (viewModel.isPrivacyChipVisible) {
            Box(modifier = Modifier.height(ShadeHeader.Dimensions.StatusBarHeight).fillMaxWidth()) {
                PrivacyChip(viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd))
                PrivacyChip(
                    privacyList = viewModel.privacyItems,
                    onClick = viewModel::onPrivacyChipClicked,
                    modifier = Modifier.align(Alignment.CenterEnd),
                )
            }
        }
        Column(
@@ -316,10 +319,11 @@ fun ContentScope.ExpandedShadeHeader(
                        useExpandedFormat = useExpandedFormat,
                        modifier = Modifier.padding(end = paddingEnd).weight(1f, fill = false),
                    )
                    BatteryIcon(
                    BatteryInfo(
                        viewModel = viewModel,
                        showIcon = true,
                        useExpandedFormat = useExpandedFormat,
                        createBatteryMeterViewController =
                            viewModel.createBatteryMeterViewController,
                        textColor = Color.White, // Single shade is always in Dark theme
                    )
                }
            }
@@ -342,8 +346,6 @@ fun ContentScope.OverlayShadeHeader(
    val horizontalPadding =
        max(LocalScreenCornerRadius.current / 2f, Shade.Dimensions.HorizontalPadding)

    val isPrivacyChipVisible by viewModel.isPrivacyChipVisible.collectAsStateWithLifecycle()

    // This layout assumes it is globally positioned at (0, 0) and is the same size as the screen.
    CutoutAwareShadeHeader(
        modifier = modifier,
@@ -412,17 +414,18 @@ fun ContentScope.OverlayShadeHeader(
                        modifier = Modifier.padding(end = paddingEnd).weight(1f, fill = false),
                        isHighlighted = isHighlighted,
                    )
                    BatteryIcon(
                        createBatteryMeterViewController =
                            viewModel.createBatteryMeterViewController,
                    BatteryInfo(
                        viewModel = viewModel,
                        showIcon = true,
                        useExpandedFormat = false,
                        isHighlighted = isHighlighted,
                    )
                }
                if (isPrivacyChipVisible) {
                if (viewModel.isPrivacyChipVisible) {
                    Box(modifier = Modifier.fillMaxSize().padding(horizontal = horizontalPadding)) {
                        PrivacyChip(
                            viewModel = viewModel,
                            privacyList = viewModel.privacyItems,
                            onClick = viewModel::onPrivacyChipClicked,
                            modifier = Modifier.align(Alignment.CenterEnd),
                        )
                    }
@@ -441,10 +444,7 @@ fun QuickSettingsOverlayHeader(viewModel: ShadeHeaderViewModel, modifier: Modifi
        modifier = modifier.fillMaxWidth(),
    ) {
        ShadeCarrierGroup(viewModel = viewModel)
        BatteryIcon(
            createBatteryMeterViewController = viewModel.createBatteryMeterViewController,
            useExpandedFormat = true,
        )
        BatteryInfo(viewModel = viewModel, showIcon = false, useExpandedFormat = true)
    }
}

@@ -546,12 +546,42 @@ private fun ContentScope.Clock(
}

@Composable
private fun BatteryIcon(
private fun BatteryInfo(
    viewModel: ShadeHeaderViewModel,
    showIcon: Boolean,
    useExpandedFormat: Boolean,
    modifier: Modifier = Modifier,
    isHighlighted: Boolean = false,
    textColor: Color = MaterialTheme.colorScheme.onSurface,
) {
    if (NewStatusBarIcons.isEnabled) {
        BatteryWithEstimate(
            viewModelFactory = viewModel.batteryViewModelFactory,
            isDarkProvider = { viewModel.isShadeAreaDark },
            showIcon = showIcon,
            showEstimate = useExpandedFormat,
            textColor = textColor,
            modifier = modifier,
        )
    } else {
        BatteryIconLegacy(
            createBatteryMeterViewController = viewModel.createBatteryMeterViewController,
            useExpandedFormat = useExpandedFormat,
            modifier = modifier,
            isHighlighted = isHighlighted,
        )
    }
}

@Composable
private fun BatteryIconLegacy(
    createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController,
    useExpandedFormat: Boolean,
    modifier: Modifier = Modifier,
    isHighlighted: Boolean = false,
) {
    NewStatusBarIcons.assertInLegacyMode()

    val localContext = LocalContext.current
    val themedContext =
        ContextThemeWrapper(localContext, R.style.Theme_SystemUI_QuickSettings_Header)
@@ -693,13 +723,6 @@ private fun ContentScope.StatusIcons(
    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 isSingleCarrier by viewModel.isSingleCarrier.collectAsStateWithLifecycle()
    val isPrivacyChipEnabled by viewModel.isPrivacyChipEnabled.collectAsStateWithLifecycle()
    val isMicCameraIndicationEnabled by
        viewModel.isMicCameraIndicationEnabled.collectAsStateWithLifecycle()
    val isLocationIndicationEnabled by
        viewModel.isLocationIndicationEnabled.collectAsStateWithLifecycle()

    val iconContainer = remember { StatusIconContainer(themedContext, null) }
    val iconManager = remember {
        viewModel.createTintedIconManager(iconContainer, StatusBarLocation.QS)
@@ -717,21 +740,21 @@ private fun ContentScope.StatusIcons(
            iconContainer.setQsExpansionTransitioning(
                layoutState.isTransitioningBetween(Scenes.Shade, Scenes.QuickSettings)
            )
            if (isSingleCarrier || !useExpandedFormat) {
            if (viewModel.isSingleCarrier || !useExpandedFormat) {
                iconContainer.removeIgnoredSlots(carrierIconSlots)
            } else {
                iconContainer.addIgnoredSlots(carrierIconSlots)
            }

            if (isPrivacyChipEnabled) {
                if (isMicCameraIndicationEnabled) {
            if (viewModel.isPrivacyChipEnabled) {
                if (viewModel.isMicCameraIndicationEnabled) {
                    iconContainer.addIgnoredSlot(cameraSlot)
                    iconContainer.addIgnoredSlot(micSlot)
                } else {
                    iconContainer.removeIgnoredSlot(cameraSlot)
                    iconContainer.removeIgnoredSlot(micSlot)
                }
                if (isLocationIndicationEnabled) {
                if (viewModel.isLocationIndicationEnabled) {
                    iconContainer.addIgnoredSlot(locationSlot)
                } else {
                    iconContainer.removeIgnoredSlot(locationSlot)
@@ -799,17 +822,16 @@ private fun SystemIconChip(

@Composable
private fun ContentScope.PrivacyChip(
    viewModel: ShadeHeaderViewModel,
    privacyList: List<PrivacyItem>,
    onClick: (OngoingPrivacyChip) -> Unit,
    modifier: Modifier = Modifier,
) {
    val privacyList by viewModel.privacyItems.collectAsStateWithLifecycle()

    AndroidView(
        factory = { context ->
            val view =
                OngoingPrivacyChip(context, null).also { privacyChip ->
                    privacyChip.privacyList = privacyList
                    privacyChip.setOnClickListener { viewModel.onPrivacyChipClicked(privacyChip) }
                    privacyChip.setOnClickListener { onClick(privacyChip) }
                }
            view
        },
+0 −72
Original line number Diff line number Diff line
@@ -19,19 +19,14 @@ package com.android.systemui.shade.domain.interactor
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.privacy.PrivacyApplication
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.privacy.PrivacyType
import com.android.systemui.privacy.privacyDialogController
import com.android.systemui.privacy.privacyDialogControllerV2
import com.android.systemui.shade.data.repository.fakePrivacyChipRepository
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -61,73 +56,6 @@ class PrivacyChipInteractorTest : SysuiTestCase() {
        whenever(privacyChip.context).thenReturn(this.context)
    }

    @Test
    fun isChipVisible_updates() =
        testScope.runTest {
            val actual by collectLastValue(underTest.isChipVisible)

            privacyChipRepository.setPrivacyItems(emptyList())
            runCurrent()

            assertThat(actual).isFalse()

            val privacyItems =
                listOf(
                    PrivacyItem(
                        privacyType = PrivacyType.TYPE_CAMERA,
                        application = PrivacyApplication("", 0)
                    ),
                )
            privacyChipRepository.setPrivacyItems(privacyItems)
            runCurrent()

            assertThat(actual).isTrue()
        }

    @Test
    fun isChipEnabled_noIndicationEnabled() =
        testScope.runTest {
            val actual by collectLastValue(underTest.isChipEnabled)

            privacyChipRepository.setIsMicCameraIndicationEnabled(false)
            privacyChipRepository.setIsLocationIndicationEnabled(false)

            assertThat(actual).isFalse()
        }

    @Test
    fun isChipEnabled_micCameraIndicationEnabled() =
        testScope.runTest {
            val actual by collectLastValue(underTest.isChipEnabled)

            privacyChipRepository.setIsMicCameraIndicationEnabled(true)
            privacyChipRepository.setIsLocationIndicationEnabled(false)

            assertThat(actual).isTrue()
        }

    @Test
    fun isChipEnabled_locationIndicationEnabled() =
        testScope.runTest {
            val actual by collectLastValue(underTest.isChipEnabled)

            privacyChipRepository.setIsMicCameraIndicationEnabled(false)
            privacyChipRepository.setIsLocationIndicationEnabled(true)

            assertThat(actual).isTrue()
        }

    @Test
    fun isChipEnabled_allIndicationEnabled() =
        testScope.runTest {
            val actual by collectLastValue(underTest.isChipEnabled)

            privacyChipRepository.setIsMicCameraIndicationEnabled(true)
            privacyChipRepository.setIsLocationIndicationEnabled(true)

            assertThat(actual).isTrue()
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun onPrivacyChipClicked_safetyCenterEnabled() =
+61 −21
Original line number Diff line number Diff line
@@ -15,13 +15,18 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.plugins.activityStarter
import com.android.systemui.privacy.PrivacyApplication
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.privacy.PrivacyType
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.fakePrivacyChipRepository
import com.android.systemui.shade.domain.interactor.disableDualShade
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeMode
@@ -31,10 +36,8 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobi
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.argThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -44,7 +47,6 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableSceneContainer
@@ -66,12 +68,10 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
    fun mobileSubIds_update() =
        testScope.runTest {
            mobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1)
            runCurrent()

            assertThat(underTest.mobileSubIds).isEqualTo(listOf(1))

            mobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
            runCurrent()

            assertThat(underTest.mobileSubIds).isEqualTo(listOf(1, 2))
        }
@@ -110,7 +110,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            setScene(Scenes.Shade)

            underTest.onSystemIconChipClicked()
            runCurrent()

            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
        }
@@ -123,7 +122,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onSystemIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).isEmpty()
@@ -137,7 +135,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onSystemIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).contains(Overlays.QuickSettingsShade)
@@ -152,7 +149,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            setScene(Scenes.Shade)

            underTest.onSystemIconChipClicked()
            runCurrent()

            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Gone)
        }
@@ -165,7 +161,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onSystemIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(currentOverlays).isEmpty()
@@ -179,7 +174,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onSystemIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(currentOverlays).contains(Overlays.QuickSettingsShade)
@@ -194,7 +188,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onNotificationIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).isEmpty()
@@ -208,7 +201,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onNotificationIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).contains(Overlays.NotificationsShade)
@@ -223,7 +215,6 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onNotificationIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(currentOverlays).isEmpty()
@@ -237,13 +228,67 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            underTest.onNotificationIconChipClicked()
            runCurrent()

            assertThat(currentScene).isEqualTo(Scenes.Gone)
            assertThat(currentOverlays).contains(Overlays.NotificationsShade)
            assertThat(currentOverlays).doesNotContain(Overlays.QuickSettingsShade)
        }

    @Test
    fun isPrivacyChipVisible_updates() =
        kosmos.runTest {
            fakePrivacyChipRepository.setPrivacyItems(emptyList())

            assertThat(underTest.isPrivacyChipVisible).isFalse()

            fakePrivacyChipRepository.setPrivacyItems(
                listOf(
                    PrivacyItem(
                        privacyType = PrivacyType.TYPE_CAMERA,
                        application = PrivacyApplication("", 0),
                    )
                )
            )

            assertThat(underTest.isPrivacyChipVisible).isTrue()
        }

    @Test
    fun isPrivacyChipEnabled_noIndicationEnabled() =
        kosmos.runTest {
            fakePrivacyChipRepository.setIsMicCameraIndicationEnabled(false)
            fakePrivacyChipRepository.setIsLocationIndicationEnabled(false)

            assertThat(underTest.isPrivacyChipEnabled).isFalse()
        }

    @Test
    fun isPrivacyChipEnabled_micCameraIndicationEnabled() =
        kosmos.runTest {
            fakePrivacyChipRepository.setIsMicCameraIndicationEnabled(true)
            fakePrivacyChipRepository.setIsLocationIndicationEnabled(false)

            assertThat(underTest.isPrivacyChipEnabled).isTrue()
        }

    @Test
    fun isPrivacyChipEnabled_locationIndicationEnabled() =
        kosmos.runTest {
            fakePrivacyChipRepository.setIsMicCameraIndicationEnabled(false)
            fakePrivacyChipRepository.setIsLocationIndicationEnabled(true)

            assertThat(underTest.isPrivacyChipEnabled).isTrue()
        }

    @Test
    fun isPrivacyChipEnabled_allIndicationEnabled() =
        kosmos.runTest {
            fakePrivacyChipRepository.setIsMicCameraIndicationEnabled(true)
            fakePrivacyChipRepository.setIsLocationIndicationEnabled(true)

            assertThat(underTest.isPrivacyChipEnabled).isTrue()
        }

    companion object {
        private val SUB_1 =
            SubscriptionModel(
@@ -272,19 +317,16 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
                SuccessFingerprintAuthenticationStatus(0, true)
            )
        }
        runCurrent()
        assertThat(shadeMode).isEqualTo(ShadeMode.Dual)

        sceneInteractor.changeScene(scene, "test")
        checkNotNull(currentOverlays).forEach { sceneInteractor.instantlyHideOverlay(it, "test") }
        runCurrent()
        overlay?.let { sceneInteractor.showOverlay(it, "test") }
        sceneInteractor.setTransitionState(
            MutableStateFlow<ObservableTransitionState>(
                ObservableTransitionState.Idle(scene, setOfNotNull(overlay))
            )
        )
        runCurrent()

        assertThat(currentScene).isEqualTo(scene)
        if (overlay == null) {
@@ -299,16 +341,14 @@ class ShadeHeaderViewModelTest : SysuiTestCase() {
        sceneInteractor.setTransitionState(
            MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(key))
        )
        testScope.runCurrent()
    }

    private fun TestScope.setDeviceEntered(isEntered: Boolean) {
    private fun setDeviceEntered(isEntered: Boolean) {
        if (isEntered) {
            // Unlock the device marking the device has entered.
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
            runCurrent()
        }
        setScene(
            if (isEntered) {
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ abstract class ExclusiveActivatable : Activatable {

    final override suspend fun activate(): Nothing {
        val allowed = _isActive.compareAndSet(false, true)
        check(allowed) { "Cannot activate an already active ExclusiveActivatable!" }
        check(allowed) { "Cannot activate an already active ExclusiveActivatable! $this" }

        try {
            onActivated()
+7 −0
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackRebind
import com.android.systemui.statusbar.notification.stack.NotificationStackRebindingHiderImpl
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl
import com.android.systemui.statusbar.phone.ConfigurationForwarder
import com.android.systemui.statusbar.phone.domain.interactor.ShadeDarkIconInteractor
import com.android.systemui.statusbar.phone.domain.interactor.ShadeDarkIconInteractorImpl
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.utils.windowmanager.WindowManagerProvider
import com.android.window.flags.Flags
@@ -341,6 +343,11 @@ object ShadeDisplayAwareWithShadeWindowModule {
    fun bindNotificationStackRebindingHider(
        impl: NotificationStackRebindingHiderImpl
    ): NotificationStackRebindingHider = impl

    @Provides
    @SysUISingleton
    fun bindShadeDarkIconInteractor(impl: ShadeDarkIconInteractorImpl): ShadeDarkIconInteractor =
        impl
}

/**
Loading