Loading packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt +4 −1 Original line number Diff line number Diff line Loading @@ -156,6 +156,7 @@ fun FooterActions(viewModel: FooterActionsViewModel, modifier: Modifier = Modifi mutableStateOf<FooterActionsForegroundServicesButtonViewModel?>(null) } var userSwitcher by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) } var settings by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) } var textFeedback by remember { mutableStateOf<TextFeedbackViewModel>(TextFeedbackViewModel.NoFeedback) Loading @@ -174,12 +175,14 @@ fun FooterActions(viewModel: FooterActionsViewModel, modifier: Modifier = Modifi viewModel.foregroundServices, viewModel.userSwitcher, viewModel.textFeedback, viewModel.settings, minActiveState = Lifecycle.State.RESUMED, ) { launch { viewModel.security.collect { security = it } } launch { viewModel.foregroundServices.collect { foregroundServices = it } } launch { viewModel.userSwitcher.collect { userSwitcher = it } } launch { viewModel.textFeedback.collect { textFeedback = it } } launch { viewModel.settings.collect { settings = it } } } val backgroundColor = Loading Loading @@ -253,7 +256,7 @@ fun FooterActions(viewModel: FooterActionsViewModel, modifier: Modifier = Modifi Modifier.sysuiResTag("multi_user_switch"), ) IconButton( { viewModel.settings }, { settings }, useModifierBasedExpandable, Modifier.sysuiResTag("settings_button_container"), ) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt +62 −5 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package com.android.systemui.qs.footer.ui.viewmodel import android.app.supervision.flags.Flags import android.content.pm.UserInfo import android.graphics.drawable.Drawable import android.os.UserHandle import android.os.UserManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags Loading @@ -29,6 +31,7 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake import com.android.settingslib.Utils import com.android.settingslib.drawable.UserIconDrawable import com.android.systemui.Flags as SysUiFlags import com.android.systemui.InstanceIdSequenceFake import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher Loading @@ -54,6 +57,9 @@ import com.android.systemui.statusbar.policy.FakeSecurityController import com.android.systemui.statusbar.policy.FakeUserInfoController import com.android.systemui.statusbar.policy.FakeUserInfoController.FakeInfo import com.android.systemui.statusbar.policy.MockUserSwitcherControllerWrapper import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.domain.interactor.HeadlessSystemUserModeFake import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable import com.android.systemui.util.settings.FakeGlobalSettings Loading @@ -61,6 +67,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle Loading @@ -80,6 +87,8 @@ import org.mockito.kotlin.eq class FooterActionsViewModelTest : SysuiTestCase() { private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) private val userRepository = FakeUserRepository() private val selectedUserInteractor = SelectedUserInteractor(userRepository) private lateinit var utils: FooterActionsTestUtils private val themedContext = ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings) Loading @@ -87,6 +96,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { @Before fun setUp() { utils = FooterActionsTestUtils(context, TestableLooper.get(this), testScope.testScheduler) userRepository.setUserInfos(USER_INFOS) } private fun runTest(block: suspend TestScope.() -> Unit) { Loading @@ -94,22 +104,66 @@ class FooterActionsViewModelTest : SysuiTestCase() { } @Test @DisableFlags(SysUiFlags.FLAG_HSU_QS_CHANGES) fun settingsButton() = runTest { val underTest = utils.footerActionsViewModel(showPowerButton = false) val settings = underTest.settings val underTest = utils.footerActionsViewModel( showPowerButton = false, selectedUserInteractor = selectedUserInteractor, ) runBlocking { userRepository.setSelectedUserInfo(USER) } val settings by collectLastValue(underTest.settings) assertThat(settings.icon) assertThat(settings).isNotNull() assertThat(settings?.icon) .isEqualTo( Icon.Resource( R.drawable.ic_qs_footer_settings, ContentDescription.Resource(R.string.accessibility_quick_settings_settings), ) ) assertThat(settings.backgroundColorFallback).isEqualTo(R.attr.shadeInactive) assertThat(settings.iconTintFallback) assertThat(settings?.backgroundColorFallback).isEqualTo(R.attr.shadeInactive) assertThat(settings?.iconTintFallback) .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeInactiveVariant)) } @Test @EnableFlags(SysUiFlags.FLAG_HSU_QS_CHANGES) fun settingsButton_hideForHeadlessSystemUser() = runTest { val fakeHsum = HeadlessSystemUserModeFake() fakeHsum.setIsHeadlessSystemUser(true) val underTest = utils.footerActionsViewModel( showPowerButton = false, hsum = fakeHsum, selectedUserInteractor = selectedUserInteractor, ) runBlocking { userRepository.setSelectedUserInfo(USER) } val settings by collectLastValue(underTest.settings) assertThat(settings).isNull() } @Test @EnableFlags(SysUiFlags.FLAG_HSU_QS_CHANGES) fun settingsButton_showWhenNotHeadlessSystemUser() = runTest { val fakeHsum = HeadlessSystemUserModeFake() fakeHsum.setIsHeadlessSystemUser(false) val underTest = utils.footerActionsViewModel( showPowerButton = false, hsum = fakeHsum, selectedUserInteractor = selectedUserInteractor, ) runBlocking { userRepository.setSelectedUserInfo(USER) } val settings by collectLastValue(underTest.settings) assertThat(settings).isNotNull() } @Test fun powerButton() = runTest { // Without power button. Loading Loading @@ -543,6 +597,9 @@ class FooterActionsViewModelTest : SysuiTestCase() { companion object { val AIRPLANE_MODE_TILE_SPEC = TileSpec.create(ConnectivityModule.AIRPLANE_MODE_TILE_SPEC) private val USER = UserInfo(UserHandle.USER_SYSTEM, "system_user", 0) private val USER_INFOS = listOf(USER) private fun createAndPopulateQsTileConfigProvider(): QSTileConfigProvider { val logger = QsEventLoggerFake(UiEventLoggerFake(), InstanceIdSequenceFake(Int.MAX_VALUE)) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelTest.kt +55 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,13 @@ package com.android.systemui.qs.panels.ui.viewmodel.toolbar import android.content.pm.UserInfo import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_HSU_QS_CHANGES import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Icon import com.android.systemui.kosmos.Kosmos Loading @@ -31,6 +36,10 @@ import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig import com.android.systemui.qs.footerActionsInteractor import com.android.systemui.res.R import com.android.systemui.testKosmos import com.android.systemui.user.data.model.SelectedUserModel import com.android.systemui.user.data.model.SelectionStatus import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.user.domain.interactor.fakeHeadlessSystemUserMode import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds Loading Loading @@ -152,11 +161,57 @@ class ToolbarViewModelTest : SysuiTestCase() { } } @Test @DisableFlags(FLAG_HSU_QS_CHANGES) fun settingsButton_isNotNullWithFlagDisabled() = with(kosmos) { runTest { selectSystemUser() assertThat(underTest.settingsButtonViewModel).isNotNull() } } @Test @EnableFlags(FLAG_HSU_QS_CHANGES) fun settingsButton_hideForHeadlessSystemUser() = with(kosmos) { runTest { fakeHeadlessSystemUserMode.setIsHeadlessSystemUser(true) selectSystemUser() assertThat(underTest.settingsButtonViewModel).isNull() } } @Test @EnableFlags(FLAG_HSU_QS_CHANGES) fun settingsButton_showWhenNotHeadlessSystemUser() = with(kosmos) { runTest { fakeHeadlessSystemUserMode.setIsHeadlessSystemUser(false) selectSystemUser() assertThat(underTest.settingsButtonViewModel).isNotNull() } } private fun Kosmos.setSecurityConfig(config: SecurityButtonConfig?) { footerActionsInteractor.fake.setSecurityConfig(config) runCurrent() } private fun Kosmos.selectSystemUser() { kosmos.fakeUserRepository.selectedUser.value = SelectedUserModel( userInfo = UserInfo(UserHandle.USER_SYSTEM, "system_user", 0), selectionStatus = SelectionStatus.SELECTION_COMPLETE, ) runCurrent() } private companion object { val MANAGED_CONFIG = SecurityButtonConfig( Loading packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +20 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleOwner import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.Flags.hsuQsChanges import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon Loading @@ -45,6 +46,8 @@ import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackContentViewModel. import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackViewModel import com.android.systemui.res.R import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.icuMessageFormat import javax.inject.Inject import javax.inject.Named Loading Loading @@ -76,7 +79,7 @@ class FooterActionsViewModel( val userSwitcher: Flow<FooterActionsButtonViewModel?>, /** The model for the settings button. */ val settings: FooterActionsButtonViewModel, val settings: Flow<FooterActionsButtonViewModel?>, /** The model for the power button. */ val power: FooterActionsButtonViewModel?, Loading Loading @@ -128,6 +131,8 @@ class FooterActionsViewModel( private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>, private val activityStarter: ActivityStarter, private val textFeedbackInteractor: TextFeedbackInteractor, private val selectedUserInteractor: SelectedUserInteractor, private val hsum: HeadlessSystemUserMode, @Named(PM_LITE_ENABLED) private val showPowerButton: Boolean, ) { /** Create a [FooterActionsViewModel] bound to the lifecycle of [lifecycleOwner]. */ Loading Loading @@ -156,6 +161,8 @@ class FooterActionsViewModel( globalActionsDialogLite, activityStarter, showPowerButton, selectedUserInteractor, hsum, ) } Loading @@ -181,6 +188,8 @@ class FooterActionsViewModel( globalActionsDialogLite, activityStarter, showPowerButton, selectedUserInteractor, hsum, ) } } Loading @@ -194,6 +203,8 @@ fun createFooterActionsViewModel( globalActionsDialogLite: GlobalActionsDialogLite, activityStarter: ActivityStarter, showPowerButton: Boolean, selectedUserInteractor: SelectedUserInteractor, hsum: HeadlessSystemUserMode, ): FooterActionsViewModel { suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) { footerActionsInteractor.deviceMonitoringDialogRequests.collect { Loading Loading @@ -285,7 +296,14 @@ fun createFooterActionsViewModel( val userSwitcher = userSwitcherViewModel(qsThemedContext, footerActionsInteractor, ::onUserSwitcherClicked) val settings = SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked) val settings = selectedUserInteractor.selectedUser .map { selectedUserId -> SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked).takeUnless { hsuQsChanges() && hsum.isHeadlessSystemUser(selectedUserId) } } .distinctUntilChanged() val power = if (showPowerButton) { Loading packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt +17 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.view.ContextThemeWrapper import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import com.android.systemui.Flags.hsuQsChanges import com.android.systemui.animation.Expandable import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.classifier.domain.interactor.runIfNotFalseTap Loading @@ -38,6 +39,8 @@ import com.android.systemui.qs.footer.ui.viewmodel.userSwitcherViewModel import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackContentViewModel import com.android.systemui.res.R import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode import com.android.systemui.user.domain.interactor.SelectedUserInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import javax.inject.Provider Loading @@ -59,6 +62,8 @@ constructor( private val footerActionsInteractor: FooterActionsInteractor, private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>, private val falsingInteractor: FalsingInteractor, private val selectedUserInteractor: SelectedUserInteractor, private val hsum: HeadlessSystemUserMode, @ShadeDisplayAware appContext: Context, @Main private val mainDispatcher: CoroutineDispatcher, ) : ExclusiveActivatable() { Loading @@ -69,9 +74,6 @@ constructor( val powerButtonViewModel: FooterActionsButtonViewModel = PowerActionViewModel(context = qsThemedContext, onClick = ::onPowerButtonClicked) val settingsButtonViewModel = SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked) val userSwitcherViewModel: FooterActionsButtonViewModel? by hydrator.hydratedStateOf( traceName = "userSwitcherViewModel", Loading @@ -84,6 +86,18 @@ constructor( ), ) val settingsButtonViewModel: FooterActionsButtonViewModel? by hydrator.hydratedStateOf( traceName = "settingsButtonViewModel", initialValue = null, source = selectedUserInteractor.selectedUser.map { selectedUserId -> SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked).takeUnless { hsuQsChanges() && hsum.isHeadlessSystemUser(selectedUserId) } }, ) var securityInfoViewModel: FooterActionsSecurityButtonViewModel? by mutableStateOf(null) private set Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt +4 −1 Original line number Diff line number Diff line Loading @@ -156,6 +156,7 @@ fun FooterActions(viewModel: FooterActionsViewModel, modifier: Modifier = Modifi mutableStateOf<FooterActionsForegroundServicesButtonViewModel?>(null) } var userSwitcher by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) } var settings by remember { mutableStateOf<FooterActionsButtonViewModel?>(null) } var textFeedback by remember { mutableStateOf<TextFeedbackViewModel>(TextFeedbackViewModel.NoFeedback) Loading @@ -174,12 +175,14 @@ fun FooterActions(viewModel: FooterActionsViewModel, modifier: Modifier = Modifi viewModel.foregroundServices, viewModel.userSwitcher, viewModel.textFeedback, viewModel.settings, minActiveState = Lifecycle.State.RESUMED, ) { launch { viewModel.security.collect { security = it } } launch { viewModel.foregroundServices.collect { foregroundServices = it } } launch { viewModel.userSwitcher.collect { userSwitcher = it } } launch { viewModel.textFeedback.collect { textFeedback = it } } launch { viewModel.settings.collect { settings = it } } } val backgroundColor = Loading Loading @@ -253,7 +256,7 @@ fun FooterActions(viewModel: FooterActionsViewModel, modifier: Modifier = Modifi Modifier.sysuiResTag("multi_user_switch"), ) IconButton( { viewModel.settings }, { settings }, useModifierBasedExpandable, Modifier.sysuiResTag("settings_button_container"), ) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt +62 −5 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package com.android.systemui.qs.footer.ui.viewmodel import android.app.supervision.flags.Flags import android.content.pm.UserInfo import android.graphics.drawable.Drawable import android.os.UserHandle import android.os.UserManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags Loading @@ -29,6 +31,7 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake import com.android.settingslib.Utils import com.android.settingslib.drawable.UserIconDrawable import com.android.systemui.Flags as SysUiFlags import com.android.systemui.InstanceIdSequenceFake import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher Loading @@ -54,6 +57,9 @@ import com.android.systemui.statusbar.policy.FakeSecurityController import com.android.systemui.statusbar.policy.FakeUserInfoController import com.android.systemui.statusbar.policy.FakeUserInfoController.FakeInfo import com.android.systemui.statusbar.policy.MockUserSwitcherControllerWrapper import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.domain.interactor.HeadlessSystemUserModeFake import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable import com.android.systemui.util.settings.FakeGlobalSettings Loading @@ -61,6 +67,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle Loading @@ -80,6 +87,8 @@ import org.mockito.kotlin.eq class FooterActionsViewModelTest : SysuiTestCase() { private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) private val userRepository = FakeUserRepository() private val selectedUserInteractor = SelectedUserInteractor(userRepository) private lateinit var utils: FooterActionsTestUtils private val themedContext = ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings) Loading @@ -87,6 +96,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { @Before fun setUp() { utils = FooterActionsTestUtils(context, TestableLooper.get(this), testScope.testScheduler) userRepository.setUserInfos(USER_INFOS) } private fun runTest(block: suspend TestScope.() -> Unit) { Loading @@ -94,22 +104,66 @@ class FooterActionsViewModelTest : SysuiTestCase() { } @Test @DisableFlags(SysUiFlags.FLAG_HSU_QS_CHANGES) fun settingsButton() = runTest { val underTest = utils.footerActionsViewModel(showPowerButton = false) val settings = underTest.settings val underTest = utils.footerActionsViewModel( showPowerButton = false, selectedUserInteractor = selectedUserInteractor, ) runBlocking { userRepository.setSelectedUserInfo(USER) } val settings by collectLastValue(underTest.settings) assertThat(settings.icon) assertThat(settings).isNotNull() assertThat(settings?.icon) .isEqualTo( Icon.Resource( R.drawable.ic_qs_footer_settings, ContentDescription.Resource(R.string.accessibility_quick_settings_settings), ) ) assertThat(settings.backgroundColorFallback).isEqualTo(R.attr.shadeInactive) assertThat(settings.iconTintFallback) assertThat(settings?.backgroundColorFallback).isEqualTo(R.attr.shadeInactive) assertThat(settings?.iconTintFallback) .isEqualTo(Utils.getColorAttrDefaultColor(themedContext, R.attr.onShadeInactiveVariant)) } @Test @EnableFlags(SysUiFlags.FLAG_HSU_QS_CHANGES) fun settingsButton_hideForHeadlessSystemUser() = runTest { val fakeHsum = HeadlessSystemUserModeFake() fakeHsum.setIsHeadlessSystemUser(true) val underTest = utils.footerActionsViewModel( showPowerButton = false, hsum = fakeHsum, selectedUserInteractor = selectedUserInteractor, ) runBlocking { userRepository.setSelectedUserInfo(USER) } val settings by collectLastValue(underTest.settings) assertThat(settings).isNull() } @Test @EnableFlags(SysUiFlags.FLAG_HSU_QS_CHANGES) fun settingsButton_showWhenNotHeadlessSystemUser() = runTest { val fakeHsum = HeadlessSystemUserModeFake() fakeHsum.setIsHeadlessSystemUser(false) val underTest = utils.footerActionsViewModel( showPowerButton = false, hsum = fakeHsum, selectedUserInteractor = selectedUserInteractor, ) runBlocking { userRepository.setSelectedUserInfo(USER) } val settings by collectLastValue(underTest.settings) assertThat(settings).isNotNull() } @Test fun powerButton() = runTest { // Without power button. Loading Loading @@ -543,6 +597,9 @@ class FooterActionsViewModelTest : SysuiTestCase() { companion object { val AIRPLANE_MODE_TILE_SPEC = TileSpec.create(ConnectivityModule.AIRPLANE_MODE_TILE_SPEC) private val USER = UserInfo(UserHandle.USER_SYSTEM, "system_user", 0) private val USER_INFOS = listOf(USER) private fun createAndPopulateQsTileConfigProvider(): QSTileConfigProvider { val logger = QsEventLoggerFake(UiEventLoggerFake(), InstanceIdSequenceFake(Int.MAX_VALUE)) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModelTest.kt +55 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,13 @@ package com.android.systemui.qs.panels.ui.viewmodel.toolbar import android.content.pm.UserInfo import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_HSU_QS_CHANGES import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Icon import com.android.systemui.kosmos.Kosmos Loading @@ -31,6 +36,10 @@ import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig import com.android.systemui.qs.footerActionsInteractor import com.android.systemui.res.R import com.android.systemui.testKosmos import com.android.systemui.user.data.model.SelectedUserModel import com.android.systemui.user.data.model.SelectionStatus import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.user.domain.interactor.fakeHeadlessSystemUserMode import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds Loading Loading @@ -152,11 +161,57 @@ class ToolbarViewModelTest : SysuiTestCase() { } } @Test @DisableFlags(FLAG_HSU_QS_CHANGES) fun settingsButton_isNotNullWithFlagDisabled() = with(kosmos) { runTest { selectSystemUser() assertThat(underTest.settingsButtonViewModel).isNotNull() } } @Test @EnableFlags(FLAG_HSU_QS_CHANGES) fun settingsButton_hideForHeadlessSystemUser() = with(kosmos) { runTest { fakeHeadlessSystemUserMode.setIsHeadlessSystemUser(true) selectSystemUser() assertThat(underTest.settingsButtonViewModel).isNull() } } @Test @EnableFlags(FLAG_HSU_QS_CHANGES) fun settingsButton_showWhenNotHeadlessSystemUser() = with(kosmos) { runTest { fakeHeadlessSystemUserMode.setIsHeadlessSystemUser(false) selectSystemUser() assertThat(underTest.settingsButtonViewModel).isNotNull() } } private fun Kosmos.setSecurityConfig(config: SecurityButtonConfig?) { footerActionsInteractor.fake.setSecurityConfig(config) runCurrent() } private fun Kosmos.selectSystemUser() { kosmos.fakeUserRepository.selectedUser.value = SelectedUserModel( userInfo = UserInfo(UserHandle.USER_SYSTEM, "system_user", 0), selectionStatus = SelectionStatus.SELECTION_COMPLETE, ) runCurrent() } private companion object { val MANAGED_CONFIG = SecurityButtonConfig( Loading
packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +20 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleOwner import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.Flags.hsuQsChanges import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon Loading @@ -45,6 +46,8 @@ import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackContentViewModel. import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackViewModel import com.android.systemui.res.R import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.icuMessageFormat import javax.inject.Inject import javax.inject.Named Loading Loading @@ -76,7 +79,7 @@ class FooterActionsViewModel( val userSwitcher: Flow<FooterActionsButtonViewModel?>, /** The model for the settings button. */ val settings: FooterActionsButtonViewModel, val settings: Flow<FooterActionsButtonViewModel?>, /** The model for the power button. */ val power: FooterActionsButtonViewModel?, Loading Loading @@ -128,6 +131,8 @@ class FooterActionsViewModel( private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>, private val activityStarter: ActivityStarter, private val textFeedbackInteractor: TextFeedbackInteractor, private val selectedUserInteractor: SelectedUserInteractor, private val hsum: HeadlessSystemUserMode, @Named(PM_LITE_ENABLED) private val showPowerButton: Boolean, ) { /** Create a [FooterActionsViewModel] bound to the lifecycle of [lifecycleOwner]. */ Loading Loading @@ -156,6 +161,8 @@ class FooterActionsViewModel( globalActionsDialogLite, activityStarter, showPowerButton, selectedUserInteractor, hsum, ) } Loading @@ -181,6 +188,8 @@ class FooterActionsViewModel( globalActionsDialogLite, activityStarter, showPowerButton, selectedUserInteractor, hsum, ) } } Loading @@ -194,6 +203,8 @@ fun createFooterActionsViewModel( globalActionsDialogLite: GlobalActionsDialogLite, activityStarter: ActivityStarter, showPowerButton: Boolean, selectedUserInteractor: SelectedUserInteractor, hsum: HeadlessSystemUserMode, ): FooterActionsViewModel { suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) { footerActionsInteractor.deviceMonitoringDialogRequests.collect { Loading Loading @@ -285,7 +296,14 @@ fun createFooterActionsViewModel( val userSwitcher = userSwitcherViewModel(qsThemedContext, footerActionsInteractor, ::onUserSwitcherClicked) val settings = SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked) val settings = selectedUserInteractor.selectedUser .map { selectedUserId -> SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked).takeUnless { hsuQsChanges() && hsum.isHeadlessSystemUser(selectedUserId) } } .distinctUntilChanged() val power = if (showPowerButton) { Loading
packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/ToolbarViewModel.kt +17 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.view.ContextThemeWrapper import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import com.android.systemui.Flags.hsuQsChanges import com.android.systemui.animation.Expandable import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.classifier.domain.interactor.runIfNotFalseTap Loading @@ -38,6 +39,8 @@ import com.android.systemui.qs.footer.ui.viewmodel.userSwitcherViewModel import com.android.systemui.qs.panels.ui.viewmodel.TextFeedbackContentViewModel import com.android.systemui.res.R import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode import com.android.systemui.user.domain.interactor.SelectedUserInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import javax.inject.Provider Loading @@ -59,6 +62,8 @@ constructor( private val footerActionsInteractor: FooterActionsInteractor, private val globalActionsDialogLiteProvider: Provider<GlobalActionsDialogLite>, private val falsingInteractor: FalsingInteractor, private val selectedUserInteractor: SelectedUserInteractor, private val hsum: HeadlessSystemUserMode, @ShadeDisplayAware appContext: Context, @Main private val mainDispatcher: CoroutineDispatcher, ) : ExclusiveActivatable() { Loading @@ -69,9 +74,6 @@ constructor( val powerButtonViewModel: FooterActionsButtonViewModel = PowerActionViewModel(context = qsThemedContext, onClick = ::onPowerButtonClicked) val settingsButtonViewModel = SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked) val userSwitcherViewModel: FooterActionsButtonViewModel? by hydrator.hydratedStateOf( traceName = "userSwitcherViewModel", Loading @@ -84,6 +86,18 @@ constructor( ), ) val settingsButtonViewModel: FooterActionsButtonViewModel? by hydrator.hydratedStateOf( traceName = "settingsButtonViewModel", initialValue = null, source = selectedUserInteractor.selectedUser.map { selectedUserId -> SettingsActionViewModel(qsThemedContext, ::onSettingsButtonClicked).takeUnless { hsuQsChanges() && hsum.isHeadlessSystemUser(selectedUserId) } }, ) var securityInfoViewModel: FooterActionsSecurityButtonViewModel? by mutableStateOf(null) private set Loading