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

Commit 3c6ebae7 authored by burakov's avatar burakov
Browse files

[Dual Shade] Remove DualShade.isEnabled from FooterActionsViewModel.

This is needed to transition from flag-based activation of dual shade to
a setting.

Bug: 388793191
Test: Unit tests still pass.
Flag: com.android.systemui.scene_container
Flag: com.android.systemui.dual_shade
Change-Id: I893f452b4b8970d4f39a8c34985bacb24e2a2a6a
parent 588b6d62
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ fun FooterActions(
        mutableStateOf<FooterActionsForegroundServicesButtonViewModel?>(null)
    }
    var userSwitcher by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) }
    var power by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) }

    LaunchedEffect(
        context,
@@ -161,6 +162,7 @@ fun FooterActions(
            launch { viewModel.security.collect { security = it } }
            launch { viewModel.foregroundServices.collect { foregroundServices = it } }
            launch { viewModel.userSwitcher.collect { userSwitcher = it } }
            launch { viewModel.power.collect { power = it } }
        }
    }

@@ -220,7 +222,7 @@ fun FooterActions(
            foregroundServices?.let { ForegroundServicesButton(it) }
            userSwitcher?.let { IconButton(it, Modifier.sysuiResTag("multi_user_switch")) }
            IconButton(viewModel.settings, Modifier.sysuiResTag("settings_button_container"))
            viewModel.power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
            power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
        }
    }
}
+33 −48
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.systemui.qs.footer.FooterActionsTestUtils
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.res.R
import com.android.systemui.security.data.model.SecurityModel
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.policy.FakeSecurityController
import com.android.systemui.statusbar.policy.FakeUserInfoController
import com.android.systemui.statusbar.policy.FakeUserInfoController.FakeInfo
@@ -45,6 +46,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeGlobalSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -57,6 +59,7 @@ import org.junit.runner.RunWith
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.`when` as whenever

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@@ -78,51 +81,45 @@ class FooterActionsViewModelTest : SysuiTestCase() {

    @Test
    fun settingsButton() = runTest {
        val underTest = utils.footerActionsViewModel(showPowerButton = false)
        val underTest =
            utils.footerActionsViewModel(showPowerButton = false, shadeMode = ShadeMode.Single)
        val settings = underTest.settings

        assertThat(settings.icon)
            .isEqualTo(
                Icon.Resource(
                    R.drawable.ic_settings,
                    ContentDescription.Resource(R.string.accessibility_quick_settings_settings)
                    ContentDescription.Resource(R.string.accessibility_quick_settings_settings),
                )
            )
        assertThat(settings.backgroundColor).isEqualTo(R.attr.shadeInactive)
        assertThat(settings.iconTint)
            .isEqualTo(
                Utils.getColorAttrDefaultColor(
                    themedContext,
                    R.attr.onShadeInactiveVariant,
                )
            )
            .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeInactiveVariant))
    }

    @Test
    fun powerButton() = runTest {
        // Without power button.
        val underTestWithoutPower = utils.footerActionsViewModel(showPowerButton = false)
        assertThat(underTestWithoutPower.power).isNull()
        val underTestWithoutPower =
            utils.footerActionsViewModel(showPowerButton = false, shadeMode = ShadeMode.Single)
        val withoutPower by collectLastValue(underTestWithoutPower.power)
        assertThat(withoutPower).isNull()

        // With power button.
        val underTestWithPower = utils.footerActionsViewModel(showPowerButton = true)
        val power = underTestWithPower.power
        val underTestWithPower =
            utils.footerActionsViewModel(showPowerButton = true, shadeMode = ShadeMode.Single)
        val power by collectLastValue(underTestWithPower.power)
        assertThat(power).isNotNull()
        assertThat(power!!.icon)
        assertThat(checkNotNull(power).icon)
            .isEqualTo(
                Icon.Resource(
                    android.R.drawable.ic_lock_power_off,
                    ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu)
                    ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu),
                )
            )
        assertThat(power.backgroundColor).isEqualTo(R.attr.shadeActive)
        assertThat(power.iconTint)
            .isEqualTo(
                Utils.getColorAttrDefaultColor(
                    themedContext,
                    R.attr.onShadeActive,
                ),
            )
        assertThat(checkNotNull(power).backgroundColor).isEqualTo(R.attr.shadeActive)
        assertThat(checkNotNull(power).iconTint)
            .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeActive))
    }

    @Test
@@ -130,7 +127,6 @@ class FooterActionsViewModelTest : SysuiTestCase() {
        val picture: Drawable = mock()
        val userInfoController = FakeUserInfoController(FakeInfo(picture = picture))
        val settings = FakeGlobalSettings(testDispatcher)
        val userId = 42
        val userSwitcherControllerWrapper =
            MockUserSwitcherControllerWrapper(currentUserName = "foo")

@@ -144,6 +140,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
        val underTest =
            utils.footerActionsViewModel(
                showPowerButton = false,
                shadeMode = ShadeMode.Single,
                footerActionsInteractor =
                    utils.footerActionsInteractor(
                        userSwitcherRepository =
@@ -152,8 +149,8 @@ class FooterActionsViewModelTest : SysuiTestCase() {
                                userManager = userManager,
                                userInfoController = userInfoController,
                                userSwitcherController = userSwitcherControllerWrapper.controller,
                            ),
                            )
                    ),
            )

        // Collect the user switcher into currentUserSwitcher.
@@ -213,13 +210,12 @@ class FooterActionsViewModelTest : SysuiTestCase() {

        val underTest =
            utils.footerActionsViewModel(
                shadeMode = ShadeMode.Single,
                footerActionsInteractor =
                    utils.footerActionsInteractor(
                        qsSecurityFooterUtils = qsSecurityFooterUtils,
                        securityRepository =
                            utils.securityRepository(
                                securityController = securityController,
                            ),
                            utils.securityRepository(securityController = securityController),
                    ),
            )

@@ -261,10 +257,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
    fun foregroundServices() = runTest {
        val securityController = FakeSecurityController()
        val fgsManagerController =
            FakeFgsManagerController(
                showFooterDot = false,
                numRunningPackages = 0,
            )
            FakeFgsManagerController(showFooterDot = false, numRunningPackages = 0)
        val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()

        // Mock QSSecurityFooter to map a SecurityModel into a SecurityButtonConfig using the
@@ -276,13 +269,11 @@ class FooterActionsViewModelTest : SysuiTestCase() {

        val underTest =
            utils.footerActionsViewModel(
                shadeMode = ShadeMode.Single,
                footerActionsInteractor =
                    utils.footerActionsInteractor(
                        qsSecurityFooterUtils = qsSecurityFooterUtils,
                        securityRepository =
                            utils.securityRepository(
                                securityController,
                            ),
                        securityRepository = utils.securityRepository(securityController),
                        foregroundServicesRepository =
                            utils.foregroundServicesRepository(fgsManagerController),
                    ),
@@ -340,14 +331,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {

        // Return a fake broadcastFlow that emits 3 fake events when collected.
        val broadcastFlow = flowOf(Unit, Unit, Unit)
        whenever(
                broadcastDispatcher.broadcastFlow(
                    any(),
                    nullable(),
                    anyInt(),
                    nullable(),
                )
            )
        whenever(broadcastDispatcher.broadcastFlow(any(), nullable(), anyInt(), nullable()))
            .thenAnswer { broadcastFlow }

        // Increment nDialogRequests whenever a request to show the dialog is made by the
@@ -359,6 +343,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {

        val underTest =
            utils.footerActionsViewModel(
                shadeMode = ShadeMode.Single,
                footerActionsInteractor =
                    utils.footerActionsInteractor(
                        qsSecurityFooterUtils = qsSecurityFooterUtils,
@@ -376,7 +361,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {

    @Test
    fun alpha_inSplitShade_followsExpansion() {
        val underTest = utils.footerActionsViewModel()
        val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Split)

        underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = true)
        assertThat(underTest.alpha.value).isEqualTo(0f)
@@ -396,7 +381,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {

    @Test
    fun backgroundAlpha_inSplitShade_followsExpansion_with_0_15_delay() {
        val underTest = utils.footerActionsViewModel()
        val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Split)
        val floatTolerance = 0.01f

        underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = true)
@@ -420,7 +405,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {

    @Test
    fun alpha_inSingleShade_followsExpansion_with_0_9_delay() {
        val underTest = utils.footerActionsViewModel()
        val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Single)
        val floatTolerance = 0.01f

        underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = false)
@@ -444,7 +429,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {

    @Test
    fun backgroundAlpha_inSingleShade_always1() {
        val underTest = utils.footerActionsViewModel()
        val underTest = utils.footerActionsViewModel(shadeMode = ShadeMode.Single)

        underTest.onQuickSettingsExpansionChanged(0f, isInSplitShade = false)
        assertThat(underTest.backgroundAlpha.value).isEqualTo(1f)
+32 −21
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.util.icuMessageFormat
import javax.inject.Inject
import javax.inject.Named
@@ -52,6 +53,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive

@@ -72,7 +74,7 @@ class FooterActionsViewModel(
    val settings: FooterActionsButtonViewModel,

    /** The model for the power button. */
    val power: FooterActionsButtonViewModel?,
    val power: Flow<FooterActionsButtonViewModel?>,

    /**
     * Observe the device monitoring dialog requests and show the dialog accordingly. This function
@@ -115,6 +117,7 @@ class FooterActionsViewModel(
        @ShadeDisplayAware private val context: Context,
        private val falsingManager: FalsingManager,
        private val footerActionsInteractor: FooterActionsInteractor,
        private val shadeModeInteractor: ShadeModeInteractor,
        private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
        private val activityStarter: ActivityStarter,
        @Named(PM_LITE_ENABLED) private val showPowerButton: Boolean,
@@ -137,9 +140,10 @@ class FooterActionsViewModel(
                )
            }

            return FooterActionsViewModel(
            return createFooterActionsViewModel(
                context,
                footerActionsInteractor,
                shadeModeInteractor.shadeMode,
                falsingManager,
                globalActionsDialogLite,
                activityStarter,
@@ -161,9 +165,10 @@ class FooterActionsViewModel(
                globalActionsDialogLite.destroy()
            }

            return FooterActionsViewModel(
            return createFooterActionsViewModel(
                context,
                footerActionsInteractor,
                shadeModeInteractor.shadeMode,
                falsingManager,
                globalActionsDialogLite,
                activityStarter,
@@ -173,9 +178,10 @@ class FooterActionsViewModel(
    }
}

fun FooterActionsViewModel(
fun createFooterActionsViewModel(
    @ShadeDisplayAware appContext: Context,
    footerActionsInteractor: FooterActionsInteractor,
    shadeMode: Flow<ShadeMode>,
    falsingManager: FalsingManager,
    globalActionsDialogLite: GlobalActionsDialogLite,
    activityStarter: ActivityStarter,
@@ -270,11 +276,12 @@ fun FooterActionsViewModel(
        userSwitcherViewModel(qsThemedContext, footerActionsInteractor, ::onUserSwitcherClicked)

    val settings = settingsButtonViewModel(qsThemedContext, ::onSettingsButtonClicked)

    val power =
        if (showPowerButton) {
            powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked)
            powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked, shadeMode)
        } else {
            null
            flowOf(null)
        }

    return FooterActionsViewModel(
@@ -401,8 +408,11 @@ fun settingsButtonViewModel(
fun powerButtonViewModel(
    qsThemedContext: Context,
    onPowerButtonClicked: (Expandable) -> Unit,
): FooterActionsButtonViewModel {
    return FooterActionsButtonViewModel(
    shadeMode: Flow<ShadeMode>,
): Flow<FooterActionsButtonViewModel?> {
    return shadeMode.map { mode ->
        val isDualShade = mode is ShadeMode.Dual
        FooterActionsButtonViewModel(
            id = R.id.pm_lite,
            Icon.Resource(
                android.R.drawable.ic_lock_power_off,
@@ -411,9 +421,10 @@ fun powerButtonViewModel(
            iconTint =
                Utils.getColorAttrDefaultColor(
                    qsThemedContext,
                if (DualShade.isEnabled) R.attr.onShadeInactiveVariant else R.attr.onShadeActive,
                    if (isDualShade) R.attr.onShadeInactiveVariant else R.attr.onShadeActive,
                ),
        backgroundColor = if (DualShade.isEnabled) R.attr.shadeInactive else R.attr.shadeActive,
            backgroundColor = if (isDualShade) R.attr.shadeInactive else R.attr.shadeActive,
            onPowerButtonClicked,
        )
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ fun Toolbar(toolbarViewModelFactory: ToolbarViewModel.Factory, modifier: Modifie
        )

        Spacer(modifier = Modifier.weight(1f))
        IconButton(viewModel.powerButtonViewModel, Modifier.sysuiResTag("pm_lite"))

        viewModel.powerButtonViewModel?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
    }
}
+13 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.qs.footer.ui.viewmodel.settingsButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.userSwitcherViewModel
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Provider
@@ -48,13 +49,24 @@ constructor(
    private val footerActionsInteractor: FooterActionsInteractor,
    private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>,
    private val falsingInteractor: FalsingInteractor,
    shadeModeInteractor: ShadeModeInteractor,
    @ShadeDisplayAware appContext: Context,
) : ExclusiveActivatable() {
    private val qsThemedContext =
        ContextThemeWrapper(appContext, R.style.Theme_SystemUI_QuickSettings)
    private val hydrator = Hydrator("ToolbarViewModel.hydrator")

    val powerButtonViewModel = powerButtonViewModel(qsThemedContext, ::onPowerButtonClicked)
    val powerButtonViewModel: FooterActionsButtonViewModel? by
        hydrator.hydratedStateOf(
            traceName = "powerButtonViewModel",
            initialValue = null,
            source =
                powerButtonViewModel(
                    qsThemedContext,
                    ::onPowerButtonClicked,
                    shadeModeInteractor.shadeMode,
                ),
        )

    val settingsButtonViewModel =
        settingsButtonViewModel(qsThemedContext, ::onSettingsButtonClicked)
Loading