summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt99
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractor.kt110
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModel.kt7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt9
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/viewmodel/StatusBarUserChipViewModelKosmos.kt24
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) }