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

Commit 428b2afa authored by Chandru S's avatar Chandru S Committed by Automerger Merge Worker
Browse files

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

parents bc7867f5 07e97aab
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