Merge "Add userSwitching state to UserRepository" into tm-qpr-dev am: 07e97aab5c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20809913 Change-Id: I840e955726e87897fec63b0bcf1489bb18329267 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -17,8 +17,11 @@
|
|||||||
|
|
||||||
package com.android.systemui.user.data.repository
|
package com.android.systemui.user.data.repository
|
||||||
|
|
||||||
|
import android.app.IActivityManager
|
||||||
|
import android.app.UserSwitchObserver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.UserInfo
|
import android.content.pm.UserInfo
|
||||||
|
import android.os.IRemoteCallback
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
@@ -30,6 +33,8 @@ import com.android.systemui.dagger.SysUISingleton
|
|||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
import com.android.systemui.dagger.qualifiers.Main
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
|
||||||
import com.android.systemui.settings.UserTracker
|
import com.android.systemui.settings.UserTracker
|
||||||
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
||||||
import com.android.systemui.util.settings.GlobalSettings
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
@@ -68,6 +73,9 @@ interface UserRepository {
|
|||||||
/** [UserInfo] of the currently-selected user. */
|
/** [UserInfo] of the currently-selected user. */
|
||||||
val selectedUserInfo: Flow<UserInfo>
|
val selectedUserInfo: Flow<UserInfo>
|
||||||
|
|
||||||
|
/** Whether user switching is currently in progress. */
|
||||||
|
val userSwitchingInProgress: Flow<Boolean>
|
||||||
|
|
||||||
/** User ID of the last non-guest selected user. */
|
/** User ID of the last non-guest selected user. */
|
||||||
val lastSelectedNonGuestUserId: Int
|
val lastSelectedNonGuestUserId: Int
|
||||||
|
|
||||||
@@ -108,6 +116,8 @@ constructor(
|
|||||||
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
||||||
private val globalSettings: GlobalSettings,
|
private val globalSettings: GlobalSettings,
|
||||||
private val tracker: UserTracker,
|
private val tracker: UserTracker,
|
||||||
|
private val activityManager: IActivityManager,
|
||||||
|
featureFlags: FeatureFlags,
|
||||||
) : UserRepository {
|
) : UserRepository {
|
||||||
|
|
||||||
private val _userSwitcherSettings = MutableStateFlow(runBlocking { getSettings() })
|
private val _userSwitcherSettings = MutableStateFlow(runBlocking { getSettings() })
|
||||||
@@ -129,6 +139,10 @@ constructor(
|
|||||||
private var _isGuestUserResetting: Boolean = false
|
private var _isGuestUserResetting: Boolean = false
|
||||||
override var isGuestUserResetting: Boolean = _isGuestUserResetting
|
override var isGuestUserResetting: Boolean = _isGuestUserResetting
|
||||||
|
|
||||||
|
private val _isUserSwitchingInProgress = MutableStateFlow(false)
|
||||||
|
override val userSwitchingInProgress: Flow<Boolean>
|
||||||
|
get() = _isUserSwitchingInProgress
|
||||||
|
|
||||||
override val isGuestUserCreationScheduled = AtomicBoolean()
|
override val isGuestUserCreationScheduled = AtomicBoolean()
|
||||||
|
|
||||||
override val isStatusBarUserChipEnabled: Boolean =
|
override val isStatusBarUserChipEnabled: Boolean =
|
||||||
@@ -141,6 +155,9 @@ constructor(
|
|||||||
init {
|
init {
|
||||||
observeSelectedUser()
|
observeSelectedUser()
|
||||||
observeUserSettings()
|
observeUserSettings()
|
||||||
|
if (featureFlags.isEnabled(FACE_AUTH_REFACTOR)) {
|
||||||
|
observeUserSwitching()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun refreshUsers() {
|
override fun refreshUsers() {
|
||||||
@@ -166,6 +183,28 @@ constructor(
|
|||||||
return _userSwitcherSettings.value.isSimpleUserSwitcher
|
return _userSwitcherSettings.value.isSimpleUserSwitcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun observeUserSwitching() {
|
||||||
|
conflatedCallbackFlow {
|
||||||
|
val callback =
|
||||||
|
object : UserSwitchObserver() {
|
||||||
|
override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
|
||||||
|
trySendWithFailureLogging(true, TAG, "userSwitching started")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUserSwitchComplete(newUserId: Int) {
|
||||||
|
trySendWithFailureLogging(false, TAG, "userSwitching completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activityManager.registerUserSwitchObserver(callback, TAG)
|
||||||
|
trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
|
||||||
|
awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
|
||||||
|
}
|
||||||
|
.onEach { _isUserSwitchingInProgress.value = it }
|
||||||
|
// TODO (b/262838215), Make this stateIn and initialize directly in field declaration
|
||||||
|
// once the flag is launched
|
||||||
|
.launchIn(applicationScope)
|
||||||
|
}
|
||||||
|
|
||||||
private fun observeSelectedUser() {
|
private fun observeSelectedUser() {
|
||||||
conflatedCallbackFlow {
|
conflatedCallbackFlow {
|
||||||
fun send() {
|
fun send() {
|
||||||
|
|||||||
@@ -17,12 +17,17 @@
|
|||||||
|
|
||||||
package com.android.systemui.user.data.repository
|
package com.android.systemui.user.data.repository
|
||||||
|
|
||||||
|
import android.app.IActivityManager
|
||||||
|
import android.app.UserSwitchObserver
|
||||||
import android.content.pm.UserInfo
|
import android.content.pm.UserInfo
|
||||||
|
import android.os.IRemoteCallback
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.flags.FakeFeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
|
||||||
import com.android.systemui.settings.FakeUserTracker
|
import com.android.systemui.settings.FakeUserTracker
|
||||||
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
||||||
import com.android.systemui.util.settings.FakeSettings
|
import com.android.systemui.util.settings.FakeSettings
|
||||||
@@ -39,7 +44,14 @@ import org.junit.Before
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.Captor
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.any
|
||||||
|
import org.mockito.Mockito.anyString
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.Mockito.times
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
@@ -48,6 +60,8 @@ import org.mockito.MockitoAnnotations
|
|||||||
class UserRepositoryImplTest : SysuiTestCase() {
|
class UserRepositoryImplTest : SysuiTestCase() {
|
||||||
|
|
||||||
@Mock private lateinit var manager: UserManager
|
@Mock private lateinit var manager: UserManager
|
||||||
|
@Mock private lateinit var activityManager: IActivityManager
|
||||||
|
@Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>
|
||||||
|
|
||||||
private lateinit var underTest: UserRepositoryImpl
|
private lateinit var underTest: UserRepositoryImpl
|
||||||
|
|
||||||
@@ -214,6 +228,34 @@ class UserRepositoryImplTest : SysuiTestCase() {
|
|||||||
assertThat(selectedUserInfo?.id).isEqualTo(1)
|
assertThat(selectedUserInfo?.id).isEqualTo(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
|
||||||
|
underTest = create(this)
|
||||||
|
|
||||||
|
underTest.userSwitchingInProgress.launchIn(this)
|
||||||
|
underTest.userSwitchingInProgress.launchIn(this)
|
||||||
|
underTest.userSwitchingInProgress.launchIn(this)
|
||||||
|
|
||||||
|
verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
|
||||||
|
underTest = create(this)
|
||||||
|
verify(activityManager)
|
||||||
|
.registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
|
||||||
|
|
||||||
|
userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
|
||||||
|
|
||||||
|
var mostRecentSwitchingValue = false
|
||||||
|
underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(mostRecentSwitchingValue).isTrue()
|
||||||
|
|
||||||
|
userSwitchObserver.value.onUserSwitchComplete(0)
|
||||||
|
assertThat(mostRecentSwitchingValue).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
private fun createUserInfo(
|
private fun createUserInfo(
|
||||||
id: Int,
|
id: Int,
|
||||||
isGuest: Boolean,
|
isGuest: Boolean,
|
||||||
@@ -280,6 +322,8 @@ class UserRepositoryImplTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
|
private fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
|
||||||
|
val featureFlags = FakeFeatureFlags()
|
||||||
|
featureFlags.set(FACE_AUTH_REFACTOR, true)
|
||||||
return UserRepositoryImpl(
|
return UserRepositoryImpl(
|
||||||
appContext = context,
|
appContext = context,
|
||||||
manager = manager,
|
manager = manager,
|
||||||
@@ -288,6 +332,8 @@ class UserRepositoryImplTest : SysuiTestCase() {
|
|||||||
backgroundDispatcher = IMMEDIATE,
|
backgroundDispatcher = IMMEDIATE,
|
||||||
globalSettings = globalSettings,
|
globalSettings = globalSettings,
|
||||||
tracker = tracker,
|
tracker = tracker,
|
||||||
|
activityManager = activityManager,
|
||||||
|
featureFlags = featureFlags,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ class FakeUserRepository : UserRepository {
|
|||||||
private val _selectedUserInfo = MutableStateFlow<UserInfo?>(null)
|
private val _selectedUserInfo = MutableStateFlow<UserInfo?>(null)
|
||||||
override val selectedUserInfo: Flow<UserInfo> = _selectedUserInfo.filterNotNull()
|
override val selectedUserInfo: Flow<UserInfo> = _selectedUserInfo.filterNotNull()
|
||||||
|
|
||||||
|
private val _userSwitchingInProgress = MutableStateFlow(false)
|
||||||
|
override val userSwitchingInProgress: Flow<Boolean>
|
||||||
|
get() = _userSwitchingInProgress
|
||||||
|
|
||||||
override var lastSelectedNonGuestUserId: Int = UserHandle.USER_SYSTEM
|
override var lastSelectedNonGuestUserId: Int = UserHandle.USER_SYSTEM
|
||||||
|
|
||||||
private var _isGuestUserAutoCreated: Boolean = false
|
private var _isGuestUserAutoCreated: Boolean = false
|
||||||
|
|||||||
Reference in New Issue
Block a user