Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt +3 −1 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 } } } } Loading Loading @@ -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")) } } } } Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt +33 −48 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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") Loading @@ -144,6 +140,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { val underTest = utils.footerActionsViewModel( showPowerButton = false, shadeMode = ShadeMode.Single, footerActionsInteractor = utils.footerActionsInteractor( userSwitcherRepository = Loading @@ -152,8 +149,8 @@ class FooterActionsViewModelTest : SysuiTestCase() { userManager = userManager, userInfoController = userInfoController, userSwitcherController = userSwitcherControllerWrapper.controller, ), ) ), ) // Collect the user switcher into currentUserSwitcher. Loading Loading @@ -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), ), ) Loading Loading @@ -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 Loading @@ -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), ), Loading Loading @@ -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 Loading @@ -359,6 +343,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { val underTest = utils.footerActionsViewModel( shadeMode = ShadeMode.Single, footerActionsInteractor = utils.footerActionsInteractor( qsSecurityFooterUtils = qsSecurityFooterUtils, Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +32 −21 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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, Loading @@ -137,9 +140,10 @@ class FooterActionsViewModel( ) } return FooterActionsViewModel( return createFooterActionsViewModel( context, footerActionsInteractor, shadeModeInteractor.shadeMode, falsingManager, globalActionsDialogLite, activityStarter, Loading @@ -161,9 +165,10 @@ class FooterActionsViewModel( globalActionsDialogLite.destroy() } return FooterActionsViewModel( return createFooterActionsViewModel( context, footerActionsInteractor, shadeModeInteractor.shadeMode, falsingManager, globalActionsDialogLite, activityStarter, Loading @@ -173,9 +178,10 @@ class FooterActionsViewModel( } } fun FooterActionsViewModel( fun createFooterActionsViewModel( @ShadeDisplayAware appContext: Context, footerActionsInteractor: FooterActionsInteractor, shadeMode: Flow<ShadeMode>, falsingManager: FalsingManager, globalActionsDialogLite: GlobalActionsDialogLite, activityStarter: ActivityStarter, Loading Loading @@ -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( Loading Loading @@ -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, Loading @@ -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, ) } } packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt +2 −1 Original line number Diff line number Diff line Loading @@ -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")) } } } packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt +13 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt +3 −1 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 } } } } Loading Loading @@ -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")) } } } } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt +33 −48 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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") Loading @@ -144,6 +140,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { val underTest = utils.footerActionsViewModel( showPowerButton = false, shadeMode = ShadeMode.Single, footerActionsInteractor = utils.footerActionsInteractor( userSwitcherRepository = Loading @@ -152,8 +149,8 @@ class FooterActionsViewModelTest : SysuiTestCase() { userManager = userManager, userInfoController = userInfoController, userSwitcherController = userSwitcherControllerWrapper.controller, ), ) ), ) // Collect the user switcher into currentUserSwitcher. Loading Loading @@ -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), ), ) Loading Loading @@ -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 Loading @@ -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), ), Loading Loading @@ -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 Loading @@ -359,6 +343,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { val underTest = utils.footerActionsViewModel( shadeMode = ShadeMode.Single, footerActionsInteractor = utils.footerActionsInteractor( qsSecurityFooterUtils = qsSecurityFooterUtils, Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +32 −21 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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, Loading @@ -137,9 +140,10 @@ class FooterActionsViewModel( ) } return FooterActionsViewModel( return createFooterActionsViewModel( context, footerActionsInteractor, shadeModeInteractor.shadeMode, falsingManager, globalActionsDialogLite, activityStarter, Loading @@ -161,9 +165,10 @@ class FooterActionsViewModel( globalActionsDialogLite.destroy() } return FooterActionsViewModel( return createFooterActionsViewModel( context, footerActionsInteractor, shadeModeInteractor.shadeMode, falsingManager, globalActionsDialogLite, activityStarter, Loading @@ -173,9 +178,10 @@ class FooterActionsViewModel( } } fun FooterActionsViewModel( fun createFooterActionsViewModel( @ShadeDisplayAware appContext: Context, footerActionsInteractor: FooterActionsInteractor, shadeMode: Flow<ShadeMode>, falsingManager: FalsingManager, globalActionsDialogLite: GlobalActionsDialogLite, activityStarter: ActivityStarter, Loading Loading @@ -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( Loading Loading @@ -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, Loading @@ -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, ) } }
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt +2 −1 Original line number Diff line number Diff line Loading @@ -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")) } } }
packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt +13 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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