diff options
8 files changed, 194 insertions, 123 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt index 627c0d0df657..b815c6ce0c51 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone import android.app.StatusBarManager +import android.graphics.Insets import android.os.UserHandle import android.os.UserManager import android.platform.test.annotations.DisableFlags @@ -23,6 +24,7 @@ import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper +import android.testing.ViewUtils import android.view.LayoutInflater import android.view.View import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -34,17 +36,21 @@ import com.android.keyguard.logging.KeyguardLogger import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.battery.BatteryMeterViewController +import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.domain.interactor.communalSceneInteractor +import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.lockscreenToGlanceableHubTransitionViewModel import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope -import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.res.R import com.android.systemui.shade.ShadeViewStateProvider import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.StatusBarState -import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStore import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler import com.android.systemui.statusbar.phone.ui.StatusBarIconController @@ -54,13 +60,16 @@ import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.UserInfoController import com.android.systemui.statusbar.ui.viewmodel.keyguardStatusBarViewModel +import com.android.systemui.statusbar.ui.viewmodel.statusBarUserChipViewModel import com.android.systemui.testKosmos -import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel +import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Assert import org.junit.Before import org.junit.Test @@ -70,12 +79,11 @@ import org.mockito.ArgumentMatchers import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) class KeyguardStatusBarViewControllerTest : SysuiTestCase() { private lateinit var kosmos: Kosmos private lateinit var testScope: TestScope @@ -106,17 +114,11 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { @Mock private lateinit var biometricUnlockController: BiometricUnlockController - @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController - - @Mock private lateinit var statusBarContentInsetsProvider: StatusBarContentInsetsProvider - @Mock private lateinit var statusBarContentInsetsProviderStore: StatusBarContentInsetsProviderStore @Mock private lateinit var userManager: UserManager - @Mock private lateinit var statusBarUserChipViewModel: StatusBarUserChipViewModel - @Captor private lateinit var configurationListenerCaptor: ArgumentCaptor<ConfigurationController.ConfigurationListener> @@ -139,21 +141,29 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { private val fakeExecutor = FakeExecutor(FakeSystemClock()) private val backgroundExecutor = FakeExecutor(FakeSystemClock()) + private lateinit var looper: TestableLooper + @Before @Throws(Exception::class) fun setup() { + looper = TestableLooper.get(this) kosmos = testKosmos() testScope = kosmos.testScope shadeViewStateProvider = TestShadeViewStateProvider() + Mockito.`when`( + kosmos.statusBarContentInsetsProvider.getStatusBarContentInsetsForCurrentRotation() + ) + .thenReturn(Insets.of(0, 0, 0, 0)) + MockitoAnnotations.initMocks(this) Mockito.`when`(iconManagerFactory.create(ArgumentMatchers.any(), ArgumentMatchers.any())) .thenReturn(iconManager) Mockito.`when`(statusBarContentInsetsProviderStore.defaultDisplay) - .thenReturn(statusBarContentInsetsProvider) + .thenReturn(kosmos.statusBarContentInsetsProvider) allowTestableLooperAsMainThread() - TestableLooper.get(this).runWithLooper { + looper.runWithLooper { keyguardStatusBarView = Mockito.spy( LayoutInflater.from(mContext).inflate(R.layout.keyguard_status_bar, null) @@ -167,6 +177,7 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { private fun createController(): KeyguardStatusBarViewController { return KeyguardStatusBarViewController( + kosmos.testDispatcher, keyguardStatusBarView, carrierTextController, configurationController, @@ -182,10 +193,10 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { keyguardUpdateMonitor, kosmos.keyguardStatusBarViewModel, biometricUnlockController, - statusBarStateController, + kosmos.statusBarStateController, statusBarContentInsetsProviderStore, userManager, - statusBarUserChipViewModel, + kosmos.statusBarUserChipViewModel, secureSettings, commandQueue, fakeExecutor, @@ -193,6 +204,8 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { logger, statusOverlayHoverListenerFactory, kosmos.communalSceneInteractor, + kosmos.glanceableHubToLockscreenTransitionViewModel, + kosmos.lockscreenToGlanceableHubTransitionViewModel, ) } @@ -682,21 +695,22 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { } @Test - fun testNewUserSwitcherDisablesAvatar_newUiOn() { - // GIVEN the status bar user switcher chip is enabled - Mockito.`when`(statusBarUserChipViewModel.chipEnabled).thenReturn(true) + fun testNewUserSwitcherDisablesAvatar_newUiOn() = + testScope.runTest { + // GIVEN the status bar user switcher chip is enabled + kosmos.fakeUserRepository.isStatusBarUserChipEnabled = true - // WHEN the controller is created - controller = createController() + // WHEN the controller is created + controller = createController() - // THEN keyguard status bar view avatar is disabled - Truth.assertThat(keyguardStatusBarView.isKeyguardUserAvatarEnabled).isFalse() - } + // THEN keyguard status bar view avatar is disabled + Truth.assertThat(keyguardStatusBarView.isKeyguardUserAvatarEnabled).isFalse() + } @Test fun testNewUserSwitcherDisablesAvatar_newUiOff() { // GIVEN the status bar user switcher chip is disabled - Mockito.`when`(statusBarUserChipViewModel.chipEnabled).thenReturn(false) + kosmos.fakeUserRepository.isStatusBarUserChipEnabled = false // WHEN the controller is created controller = createController() @@ -752,12 +766,7 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { } private fun updateStatusBarState(state: Int) { - val statusBarStateListenerCaptor = - ArgumentCaptor.forClass(StatusBarStateController.StateListener::class.java) - Mockito.verify(statusBarStateController).addCallback(statusBarStateListenerCaptor.capture()) - val callback = statusBarStateListenerCaptor.value - - callback.onStateChanged(state) + kosmos.statusBarStateController.setState(state) } @Test @@ -774,6 +783,36 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { Truth.assertThat(keyguardStatusBarView.visibility).isEqualTo(View.INVISIBLE) } + @Test + fun animateToGlanceableHub_affectsAlpha() = + testScope.runTest { + controller.init() + val transitionAlphaAmount = .5f + ViewUtils.attachView(keyguardStatusBarView) + looper.processAllMessages() + updateStateToKeyguard() + kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Communal) + runCurrent() + controller.updateCommunalAlphaTransition(transitionAlphaAmount) + Truth.assertThat(keyguardStatusBarView.getAlpha()).isEqualTo(transitionAlphaAmount) + } + + @Test + fun animateToGlanceableHub_alphaResetOnCommunalNotShowing() = + testScope.runTest { + controller.init() + val transitionAlphaAmount = .5f + ViewUtils.attachView(keyguardStatusBarView) + looper.processAllMessages() + updateStateToKeyguard() + kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Communal) + runCurrent() + controller.updateCommunalAlphaTransition(transitionAlphaAmount) + kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Blank) + runCurrent() + Truth.assertThat(keyguardStatusBarView.getAlpha()).isNotEqualTo(transitionAlphaAmount) + } + /** * Calls [com.android.keyguard.KeyguardUpdateMonitorCallback.onFinishedGoingToSleep] to ensure * values are updated properly. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt index 67b009e50ce0..7f3ef61d02c0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt @@ -54,9 +54,7 @@ constructor( duration = TO_LOCKSCREEN_DURATION, edge = Edge.create(from = Scenes.Communal, to = LOCKSCREEN), ) - .setupWithoutSceneContainer( - edge = Edge.create(from = GLANCEABLE_HUB, to = LOCKSCREEN), - ) + .setupWithoutSceneContainer(edge = Edge.create(from = GLANCEABLE_HUB, to = LOCKSCREEN)) val keyguardAlpha: Flow<Float> = transitionAnimation.sharedFlow( @@ -75,7 +73,7 @@ constructor( configurationInteractor .directionalDimensionPixelSize( LayoutDirection.LTR, - R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x + R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x, ) .flatMapLatest { translatePx: Int -> transitionAnimation.sharedFlowWithState( @@ -87,7 +85,7 @@ constructor( // is cancelled. onFinish = { 0f }, onCancel = { 0f }, - name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardTranslationX" + name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardTranslationX", ) } @@ -95,6 +93,8 @@ constructor( val shortcutsAlpha: Flow<Float> = keyguardAlpha + val statusBarAlpha: Flow<Float> = keyguardAlpha + val notificationTranslationX: Flow<Float> = keyguardTranslationX.map { it.value }.filterNotNull() } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt index 378374e72c8b..dd8ff8c4a052 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt @@ -54,9 +54,7 @@ constructor( duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION, edge = Edge.create(from = LOCKSCREEN, to = Scenes.Communal), ) - .setupWithoutSceneContainer( - edge = Edge.create(from = LOCKSCREEN, to = GLANCEABLE_HUB), - ) + .setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = GLANCEABLE_HUB)) val keyguardAlpha: Flow<Float> = transitionAnimation.sharedFlow( @@ -74,7 +72,7 @@ constructor( configurationInteractor .directionalDimensionPixelSize( LayoutDirection.LTR, - R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x + R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x, ) .flatMapLatest { translatePx: Int -> transitionAnimation.sharedFlowWithState( @@ -86,7 +84,7 @@ constructor( onFinish = { 0f }, onCancel = { 0f }, interpolator = EMPHASIZED, - name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardTranslationX" + name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardTranslationX", ) } @@ -94,6 +92,8 @@ constructor( val shortcutsAlpha: Flow<Float> = keyguardAlpha + val statusBarAlpha: Flow<Float> = keyguardAlpha + val notificationTranslationX: Flow<Float> = keyguardTranslationX.map { it.value }.filterNotNull() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index be2fb68ab88d..2433b78fc183 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -50,6 +50,8 @@ import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel; +import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGlanceableHubTransitionViewModel; import com.android.systemui.log.core.LogLevel; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.res.R; @@ -82,6 +84,8 @@ import com.android.systemui.util.settings.SecureSettings; import kotlin.Unit; +import kotlinx.coroutines.CoroutineDispatcher; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -108,6 +112,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat R.id.keyguard_hun_animator_end_tag, R.id.keyguard_hun_animator_start_tag); + private final CoroutineDispatcher mCoroutineDispatcher; private final CarrierTextController mCarrierTextController; private final ConfigurationController mConfigurationController; private final SystemStatusAnimationScheduler mAnimationScheduler; @@ -133,6 +138,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private final Object mLock = new Object(); private final KeyguardLogger mLogger; private final CommunalSceneInteractor mCommunalSceneInteractor; + private final GlanceableHubToLockscreenTransitionViewModel mHubToLockscreenTransitionViewModel; + private final LockscreenToGlanceableHubTransitionViewModel mLockscreenToHubTransitionViewModel; private View mSystemIconsContainer; private final StatusOverlayHoverListenerFactory mStatusOverlayHoverListenerFactory; @@ -249,9 +256,20 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private boolean mCommunalShowing; private final Consumer<Boolean> mCommunalConsumer = (communalShowing) -> { + updateCommunalShowing(communalShowing); + }; + + @VisibleForTesting + void updateCommunalShowing(boolean communalShowing) { mCommunalShowing = communalShowing; + + // When communal is hidden (either by transition or state change), set alpha to fully + // visible. + if (!mCommunalShowing) { + setAlpha(-1f); + } updateViewState(); - }; + } private final DisableStateTracker mDisableStateTracker; @@ -277,6 +295,15 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private boolean mShowingKeyguardHeadsUp; private StatusBarSystemEventDefaultAnimator mSystemEventAnimator; private float mSystemEventAnimatorAlpha = 1; + private final Consumer<Float> mToGlanceableHubStatusBarAlphaConsumer = (alpha) -> + updateCommunalAlphaTransition(alpha); + + private final Consumer<Float> mFromGlanceableHubStatusBarAlphaConsumer = (alpha) -> + updateCommunalAlphaTransition(alpha); + + @VisibleForTesting void updateCommunalAlphaTransition(float alpha) { + setAlpha(!mCommunalShowing || alpha == 0 ? -1 : alpha); + } /** * The alpha value to be set on the View. If -1, this value is to be ignored. @@ -285,6 +312,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat @Inject public KeyguardStatusBarViewController( + @Main CoroutineDispatcher dispatcher, KeyguardStatusBarView view, CarrierTextController carrierTextController, ConfigurationController configurationController, @@ -310,9 +338,14 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat @Background Executor backgroundExecutor, KeyguardLogger logger, StatusOverlayHoverListenerFactory statusOverlayHoverListenerFactory, - CommunalSceneInteractor communalSceneInteractor + CommunalSceneInteractor communalSceneInteractor, + GlanceableHubToLockscreenTransitionViewModel + glanceableHubToLockscreenTransitionViewModel, + LockscreenToGlanceableHubTransitionViewModel + lockscreenToGlanceableHubTransitionViewModel ) { super(view); + mCoroutineDispatcher = dispatcher; mCarrierTextController = carrierTextController; mConfigurationController = configurationController; mAnimationScheduler = animationScheduler; @@ -337,6 +370,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat mBackgroundExecutor = backgroundExecutor; mLogger = logger; mCommunalSceneInteractor = communalSceneInteractor; + mHubToLockscreenTransitionViewModel = glanceableHubToLockscreenTransitionViewModel; + mLockscreenToHubTransitionViewModel = lockscreenToGlanceableHubTransitionViewModel; mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled(); mKeyguardStateController.addCallback( @@ -418,7 +453,12 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat UserHandle.USER_ALL); updateUserSwitcher(); onThemeChanged(); - collectFlow(mView, mCommunalSceneInteractor.isCommunalVisible(), mCommunalConsumer); + collectFlow(mView, mCommunalSceneInteractor.isCommunalVisible(), mCommunalConsumer, + mCoroutineDispatcher); + collectFlow(mView, mLockscreenToHubTransitionViewModel.getStatusBarAlpha(), + mToGlanceableHubStatusBarAlphaConsumer, mCoroutineDispatcher); + collectFlow(mView, mHubToLockscreenTransitionViewModel.getStatusBarAlpha(), + mFromGlanceableHubStatusBarAlphaConsumer, mCoroutineDispatcher); } @Override @@ -573,7 +613,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat && !mDozing && !hideForBypass && !mDisableStateTracker.isDisabled() - && !mCommunalShowing + && (!mCommunalShowing || mExplicitAlpha != -1) ? View.VISIBLE : View.INVISIBLE; updateViewState(newAlpha, newVisibility); diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt index 3662c78efb16..163288b25b28 100644 --- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt @@ -32,6 +32,7 @@ import android.os.UserHandle import android.os.UserManager import android.provider.Settings import android.util.Log +import com.android.app.tracing.coroutines.launchTraced as launch import com.android.internal.logging.UiEventLogger import com.android.internal.util.UserIcons import com.android.keyguard.KeyguardUpdateMonitor @@ -81,7 +82,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import com.android.app.tracing.coroutines.launchTraced as launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext @@ -109,7 +109,7 @@ constructor( private val guestUserInteractor: GuestUserInteractor, private val uiEventLogger: UiEventLogger, private val userRestrictionChecker: UserRestrictionChecker, - private val processWrapper: ProcessWrapper + private val processWrapper: ProcessWrapper, ) { /** * Defines interface for classes that can be notified when the state of users on the device is @@ -137,11 +137,10 @@ constructor( /** List of current on-device users to select from. */ val users: Flow<List<UserModel>> get() = - combine( + combine(userInfos, repository.selectedUserInfo, repository.userSwitcherSettings) { userInfos, - repository.selectedUserInfo, - repository.userSwitcherSettings, - ) { userInfos, selectedUserInfo, settings -> + selectedUserInfo, + settings -> toUserModels( userInfos = userInfos, selectedUserId = selectedUserInfo.id, @@ -157,7 +156,7 @@ constructor( toUserModel( userInfo = selectedUserInfo, selectedUserId = selectedUserId, - canSwitchUsers = canSwitchUsers(selectedUserId) + canSwitchUsers = canSwitchUsers(selectedUserId), ) } @@ -211,7 +210,7 @@ constructor( manager, repository, settings.isUserSwitcherEnabled, - canAccessUserSwitcher + canAccessUserSwitcher, ) if (canCreateUsers) { @@ -238,7 +237,7 @@ constructor( if ( UserActionsUtil.canManageUsers( repository, - settings.isUserSwitcherEnabled + settings.isUserSwitcherEnabled, ) ) { add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) @@ -248,18 +247,14 @@ constructor( .flowOn(backgroundDispatcher) val userRecords: StateFlow<ArrayList<UserRecord>> = - combine( + combine(userInfos, repository.selectedUserInfo, actions, repository.userSwitcherSettings) { userInfos, - repository.selectedUserInfo, - actions, - repository.userSwitcherSettings, - ) { userInfos, selectedUserInfo, actionModels, settings -> + selectedUserInfo, + actionModels, + settings -> ArrayList( userInfos.map { - toRecord( - userInfo = it, - selectedUserId = selectedUserInfo.id, - ) + toRecord(userInfo = it, selectedUserId = selectedUserInfo.id) } + actionModels.map { toRecord( @@ -298,7 +293,8 @@ constructor( val isGuestUserResetting: Boolean = guestUserInteractor.isGuestUserResetting /** Whether to enable the user chip in the status bar */ - val isStatusBarUserChipEnabled: Boolean = repository.isStatusBarUserChipEnabled + val isStatusBarUserChipEnabled: Boolean + get() = repository.isStatusBarUserChipEnabled private val _dialogShowRequests = MutableStateFlow<ShowDialogRequestModel?>(null) val dialogShowRequests: Flow<ShowDialogRequestModel?> = _dialogShowRequests.asStateFlow() @@ -467,10 +463,8 @@ constructor( when (action) { UserActionModel.ENTER_GUEST_MODE -> { uiEventLogger.log(MultiUserActionsEvent.CREATE_GUEST_FROM_USER_SWITCHER) - guestUserInteractor.createAndSwitchTo( - this::showDialog, - this::dismissDialog, - ) { userId -> + guestUserInteractor.createAndSwitchTo(this::showDialog, this::dismissDialog) { + userId -> selectUser(userId, dialogShower) } } @@ -481,7 +475,7 @@ constructor( activityStarter.startActivity( CreateUserActivity.createIntentForStart( applicationContext, - keyguardInteractor.isKeyguardShowing() + keyguardInteractor.isKeyguardShowing(), ), /* dismissShade= */ true, /* animationController */ null, @@ -523,17 +517,14 @@ constructor( ) } - fun removeGuestUser( - @UserIdInt guestUserId: Int, - @UserIdInt targetUserId: Int, - ) { + fun removeGuestUser(@UserIdInt guestUserId: Int, @UserIdInt targetUserId: Int) { applicationScope.launch { guestUserInteractor.remove( guestUserId = guestUserId, targetUserId = targetUserId, ::showDialog, ::dismissDialog, - ::switchUser + ::switchUser, ) } } @@ -570,10 +561,7 @@ constructor( } } - private suspend fun toRecord( - userInfo: UserInfo, - selectedUserId: Int, - ): UserRecord { + private suspend fun toRecord(userInfo: UserInfo, selectedUserId: Int): UserRecord { return LegacyUserDataHelper.createRecord( context = applicationContext, manager = manager, @@ -595,10 +583,7 @@ constructor( actionType = action, isRestricted = isRestricted, isSwitchToEnabled = - canSwitchUsers( - selectedUserId = selectedUserId, - isAction = true, - ) && + canSwitchUsers(selectedUserId = selectedUserId, isAction = true) && // If the user is auto-created is must not be currently resetting. !(isGuestUserAutoCreated && isGuestUserResetting), userRestrictionChecker = userRestrictionChecker, @@ -623,10 +608,7 @@ constructor( } } - private suspend fun onBroadcastReceived( - intent: Intent, - previousUserInfo: UserInfo?, - ) { + private suspend fun onBroadcastReceived(intent: Intent, previousUserInfo: UserInfo?) { val shouldRefreshAllUsers = when (intent.action) { Intent.ACTION_LOCALE_CHANGED -> true @@ -645,10 +627,8 @@ constructor( Intent.ACTION_USER_INFO_CHANGED -> true Intent.ACTION_USER_UNLOCKED -> { // If we unlocked the system user, we should refresh all users. - intent.getIntExtra( - Intent.EXTRA_USER_HANDLE, - UserHandle.USER_NULL, - ) == UserHandle.USER_SYSTEM + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) == + UserHandle.USER_SYSTEM } else -> true } @@ -668,20 +648,14 @@ constructor( // Disconnect from the old secondary user's service val secondaryUserId = repository.secondaryUserId if (secondaryUserId != UserHandle.USER_NULL) { - applicationContext.stopServiceAsUser( - intent, - UserHandle.of(secondaryUserId), - ) + applicationContext.stopServiceAsUser(intent, UserHandle.of(secondaryUserId)) repository.secondaryUserId = UserHandle.USER_NULL } // Connect to the new secondary user's service (purely to ensure that a persistent // SystemUI application is created for that user) if (userId != processWrapper.myUserHandle().identifier && !processWrapper.isSystemUser) { - applicationContext.startServiceAsUser( - intent, - UserHandle.of(userId), - ) + applicationContext.startServiceAsUser(intent, UserHandle.of(userId)) repository.secondaryUserId = userId } } @@ -732,7 +706,7 @@ constructor( private suspend fun toUserModel( userInfo: UserInfo, selectedUserId: Int, - canSwitchUsers: Boolean + canSwitchUsers: Boolean, ): UserModel { val userId = userInfo.id val isSelected = userId == selectedUserId @@ -740,11 +714,7 @@ constructor( UserModel( id = userId, name = Text.Loaded(userInfo.name), - image = - getUserImage( - isGuest = true, - userId = userId, - ), + image = getUserImage(isGuest = true, userId = userId), isSelected = isSelected, isSelectable = canSwitchUsers, isGuest = true, @@ -753,11 +723,7 @@ constructor( UserModel( id = userId, name = Text.Loaded(userInfo.name), - image = - getUserImage( - isGuest = false, - userId = userId, - ), + image = getUserImage(isGuest = false, userId = userId), isSelected = isSelected, isSelectable = canSwitchUsers || isSelected, isGuest = false, @@ -765,10 +731,7 @@ constructor( } } - private suspend fun canSwitchUsers( - selectedUserId: Int, - isAction: Boolean = false, - ): Boolean { + private suspend fun canSwitchUsers(selectedUserId: Int, isAction: Boolean = false): Boolean { val isHeadlessSystemUserMode = withContext(backgroundDispatcher) { headlessSystemUserMode.isHeadlessSystemUserMode() } // Whether menu item should be active. True if item is a user or if any user has @@ -785,7 +748,7 @@ constructor( .getUsers( /* excludePartial= */ true, /* excludeDying= */ true, - /* excludePreCreated= */ true + /* excludePreCreated= */ true, ) .any { user -> user.id != UserHandle.USER_SYSTEM && @@ -794,10 +757,7 @@ constructor( } @SuppressLint("UseCompatLoadingForDrawables") - private suspend fun getUserImage( - isGuest: Boolean, - userId: Int, - ): Drawable { + private suspend fun getUserImage(isGuest: Boolean, userId: Int): Drawable { if (isGuest) { return checkNotNull( applicationContext.getDrawable(com.android.settingslib.R.drawable.ic_account_circle) @@ -823,13 +783,13 @@ constructor( return UserIcons.getDefaultUserIcon( applicationContext.resources, userId, - /* light= */ false + /* light= */ false, ) } private fun canCreateGuestUser( settings: UserSwitcherSettingsModel, - canAccessUserSwitcher: Boolean + canAccessUserSwitcher: Boolean, ): Boolean { return guestUserInteractor.isGuestUserAutoCreated || UserActionsUtil.canCreateGuest( diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt index 2c425b199b4e..53c2d888922b 100644 --- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt @@ -30,11 +30,10 @@ import kotlinx.coroutines.flow.mapLatest @OptIn(ExperimentalCoroutinesApi::class) class StatusBarUserChipViewModel @Inject -constructor( - interactor: UserSwitcherInteractor, -) { +constructor(private val interactor: UserSwitcherInteractor) { /** Whether the status bar chip ui should be available */ - val chipEnabled: Boolean = interactor.isStatusBarUserChipEnabled + val chipEnabled: Boolean + get() = interactor.isStatusBarUserChipEnabled /** Whether or not the chip should be showing, based on the number of users */ val isChipVisible: Flow<Boolean> = diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt index 5eaa198fb2a6..a3cdcd20e93b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt @@ -51,6 +51,8 @@ import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.domain.interactor.pulseExpansionInteractor +import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.lockscreenToGlanceableHubTransitionViewModel import com.android.systemui.model.sceneContainerPlugin import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.power.data.repository.fakePowerRepository @@ -164,4 +166,11 @@ class KosmosJavaAdapter() { val msdlPlayer by lazy { kosmos.fakeMSDLPlayer } val shadeModeInteractor by lazy { kosmos.shadeModeInteractor } val bouncerHapticHelper by lazy { kosmos.bouncerHapticPlayer } + + val glanceableHubToLockscreenTransitionViewModel by lazy { + kosmos.glanceableHubToLockscreenTransitionViewModel + } + val lockscreenToGlanceableHubTransitionViewModel by lazy { + kosmos.lockscreenToGlanceableHubTransitionViewModel + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/viewmodel/StatusBarUserChipViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/viewmodel/StatusBarUserChipViewModelKosmos.kt new file mode 100644 index 000000000000..01175a568b3a --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/viewmodel/StatusBarUserChipViewModelKosmos.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.ui.viewmodel + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.user.domain.interactor.userSwitcherInteractor +import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel + +val Kosmos.statusBarUserChipViewModel: StatusBarUserChipViewModel by + Kosmos.Fixture { StatusBarUserChipViewModel(userSwitcherInteractor) } |