Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d90aac4 authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

Merge "Merge "Add userSwitching state to UserRepository" into tm-qpr-dev am:...

Merge "Merge "Add userSwitching state to UserRepository" into tm-qpr-dev am: 07e97aab am: 428b2afa"
parents 82c57ac4 f5c7d6a3
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -17,8 +17,11 @@

package com.android.systemui.user.data.repository

import android.app.IActivityManager
import android.app.UserSwitchObserver
import android.content.Context
import android.content.pm.UserInfo
import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
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.Background
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.user.data.model.UserSwitcherSettingsModel
import com.android.systemui.util.settings.GlobalSettings
@@ -68,6 +73,9 @@ interface UserRepository {
    /** [UserInfo] of the currently-selected user. */
    val selectedUserInfo: Flow<UserInfo>

    /** Whether user switching is currently in progress. */
    val userSwitchingInProgress: Flow<Boolean>

    /** User ID of the last non-guest selected user. */
    val lastSelectedNonGuestUserId: Int

@@ -108,6 +116,8 @@ constructor(
    @Background private val backgroundDispatcher: CoroutineDispatcher,
    private val globalSettings: GlobalSettings,
    private val tracker: UserTracker,
    private val activityManager: IActivityManager,
    featureFlags: FeatureFlags,
) : UserRepository {

    private val _userSwitcherSettings = MutableStateFlow(runBlocking { getSettings() })
@@ -129,6 +139,10 @@ constructor(
    private var _isGuestUserResetting: Boolean = false
    override var isGuestUserResetting: Boolean = _isGuestUserResetting

    private val _isUserSwitchingInProgress = MutableStateFlow(false)
    override val userSwitchingInProgress: Flow<Boolean>
        get() = _isUserSwitchingInProgress

    override val isGuestUserCreationScheduled = AtomicBoolean()

    override val isStatusBarUserChipEnabled: Boolean =
@@ -141,6 +155,9 @@ constructor(
    init {
        observeSelectedUser()
        observeUserSettings()
        if (featureFlags.isEnabled(FACE_AUTH_REFACTOR)) {
            observeUserSwitching()
        }
    }

    override fun refreshUsers() {
@@ -166,6 +183,28 @@ constructor(
        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() {
        conflatedCallbackFlow {
                fun send() {
+46 −0
Original line number Diff line number Diff line
@@ -17,12 +17,17 @@

package com.android.systemui.user.data.repository

import android.app.IActivityManager
import android.app.UserSwitchObserver
import android.content.pm.UserInfo
import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
import androidx.test.filters.SmallTest
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.user.data.model.UserSwitcherSettingsModel
import com.android.systemui.util.settings.FakeSettings
@@ -39,7 +44,14 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.Captor
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.MockitoAnnotations

@@ -48,6 +60,8 @@ import org.mockito.MockitoAnnotations
class UserRepositoryImplTest : SysuiTestCase() {

    @Mock private lateinit var manager: UserManager
    @Mock private lateinit var activityManager: IActivityManager
    @Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>

    private lateinit var underTest: UserRepositoryImpl

@@ -214,6 +228,34 @@ class UserRepositoryImplTest : SysuiTestCase() {
        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(
        id: Int,
        isGuest: Boolean,
@@ -280,6 +322,8 @@ class UserRepositoryImplTest : SysuiTestCase() {
        }

    private fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
        val featureFlags = FakeFeatureFlags()
        featureFlags.set(FACE_AUTH_REFACTOR, true)
        return UserRepositoryImpl(
            appContext = context,
            manager = manager,
@@ -288,6 +332,8 @@ class UserRepositoryImplTest : SysuiTestCase() {
            backgroundDispatcher = IMMEDIATE,
            globalSettings = globalSettings,
            tracker = tracker,
            activityManager = activityManager,
            featureFlags = featureFlags,
        )
    }

+4 −0
Original line number Diff line number Diff line
@@ -39,6 +39,10 @@ class FakeUserRepository : UserRepository {
    private val _selectedUserInfo = MutableStateFlow<UserInfo?>(null)
    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

    private var _isGuestUserAutoCreated: Boolean = false