Merge "Ensure secondary sysui service starts" into udc-qpr-dev am: 53e4fcbac1

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23693213

Change-Id: Iecbacaccfdee0dd58d5ceaba77b80280123d62ac
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2023-07-07 17:58:55 +00:00
committed by Automerger Merge Worker
5 changed files with 242 additions and 86 deletions

View File

@@ -27,6 +27,7 @@ import android.content.pm.UserInfo
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.os.Process
import android.os.RemoteException import android.os.RemoteException
import android.os.UserHandle import android.os.UserHandle
import android.os.UserManager import android.os.UserManager
@@ -334,6 +335,7 @@ constructor(
onBroadcastReceived(intent, previousSelectedUser) onBroadcastReceived(intent, previousSelectedUser)
} }
.launchIn(applicationScope) .launchIn(applicationScope)
restartSecondaryService(repository.getSelectedUserInfo().id)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
} }
@@ -646,7 +648,7 @@ constructor(
// Connect to the new secondary user's service (purely to ensure that a persistent // Connect to the new secondary user's service (purely to ensure that a persistent
// SystemUI application is created for that user) // SystemUI application is created for that user)
if (userId != UserHandle.USER_SYSTEM) { if (userId != Process.myUserHandle().identifier) {
applicationContext.startServiceAsUser( applicationContext.startServiceAsUser(
intent, intent,
UserHandle.of(userId), UserHandle.of(userId),

View File

@@ -20,6 +20,7 @@ import android.app.ActivityManager
import android.app.StatusBarManager.DISABLE2_NONE import android.app.StatusBarManager.DISABLE2_NONE
import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
import android.content.pm.UserInfo
import android.os.UserManager import android.os.UserManager
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger import com.android.internal.logging.UiEventLogger
@@ -47,6 +48,7 @@ import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@@ -92,6 +94,23 @@ class ShadeInteractorTest : SysuiTestCase() {
mainDispatcher = testDispatcher, mainDispatcher = testDispatcher,
repository = userRepository, repository = userRepository,
) )
runBlocking {
val userInfos =
listOf(
UserInfo(
/* id= */ 0,
/* name= */ "zero",
/* iconPath= */ "",
/* flags= */ UserInfo.FLAG_PRIMARY or
UserInfo.FLAG_ADMIN or
UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_SYSTEM,
),
)
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[0])
}
userInteractor = userInteractor =
UserInteractor( UserInteractor(
applicationContext = context, applicationContext = context,

View File

@@ -19,10 +19,12 @@ package com.android.systemui.user.domain.interactor
import android.app.ActivityManager import android.app.ActivityManager
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.UserInfo import android.content.pm.UserInfo
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Process
import android.os.UserHandle import android.os.UserHandle
import android.os.UserManager import android.os.UserManager
import android.provider.Settings import android.provider.Settings
@@ -62,7 +64,9 @@ import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertNotNull import junit.framework.Assert.assertNotNull
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@@ -76,6 +80,7 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times import org.mockito.Mockito.times
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations
@@ -99,11 +104,15 @@ class UserInteractorTest : SysuiTestCase() {
private lateinit var underTest: UserInteractor private lateinit var underTest: UserInteractor
private lateinit var spyContext: Context
private lateinit var testScope: TestScope private lateinit var testScope: TestScope
private lateinit var userRepository: FakeUserRepository private lateinit var userRepository: FakeUserRepository
private lateinit var keyguardReply: KeyguardInteractorFactory.WithDependencies
private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var telephonyRepository: FakeTelephonyRepository private lateinit var telephonyRepository: FakeTelephonyRepository
private lateinit var testDispatcher: TestDispatcher
private lateinit var featureFlags: FakeFeatureFlags private lateinit var featureFlags: FakeFeatureFlags
private lateinit var refreshUsersScheduler: RefreshUsersScheduler
@Before @Before
fun setUp() { fun setUp() {
@@ -123,58 +132,36 @@ class UserInteractorTest : SysuiTestCase() {
set(Flags.FULL_SCREEN_USER_SWITCHER, false) set(Flags.FULL_SCREEN_USER_SWITCHER, false)
set(Flags.FACE_AUTH_REFACTOR, true) set(Flags.FACE_AUTH_REFACTOR, true)
} }
val reply = KeyguardInteractorFactory.create(featureFlags = featureFlags) spyContext = spy(context)
keyguardRepository = reply.repository keyguardReply = KeyguardInteractorFactory.create(featureFlags = featureFlags)
keyguardRepository = keyguardReply.repository
userRepository = FakeUserRepository() userRepository = FakeUserRepository()
telephonyRepository = FakeTelephonyRepository() telephonyRepository = FakeTelephonyRepository()
val testDispatcher = StandardTestDispatcher() testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher) testScope = TestScope(testDispatcher)
val refreshUsersScheduler = refreshUsersScheduler =
RefreshUsersScheduler( RefreshUsersScheduler(
applicationScope = testScope.backgroundScope, applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher, mainDispatcher = testDispatcher,
repository = userRepository, repository = userRepository,
) )
underTest =
UserInteractor(
applicationContext = context,
repository = userRepository,
activityStarter = activityStarter,
keyguardInteractor = reply.keyguardInteractor,
manager = manager,
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
repository = telephonyRepository,
),
broadcastDispatcher = fakeBroadcastDispatcher,
keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor =
GuestUserInteractor(
applicationContext = context,
applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher,
backgroundDispatcher = testDispatcher,
manager = manager,
repository = userRepository,
deviceProvisionedController = deviceProvisionedController,
devicePolicyManager = devicePolicyManager,
refreshUsersScheduler = refreshUsersScheduler,
uiEventLogger = uiEventLogger,
resumeSessionReceiver = resumeSessionReceiver,
resetOrExitSessionReceiver = resetOrExitSessionReceiver,
),
uiEventLogger = uiEventLogger,
featureFlags = featureFlags,
)
} }
@Test @Test
fun testKeyguardUpdateMonitor_onKeyguardGoingAway() = fun createUserInteractor_processUser_noSecondaryService() {
createUserInteractor()
verify(spyContext, never()).startServiceAsUser(any(), any())
}
@Test
fun createUserInteractor_nonProcessUser_startsSecondaryService() {
createUserInteractor(false /* startAsProcessUser */)
verify(spyContext).startServiceAsUser(any(), any())
}
@Test
fun testKeyguardUpdateMonitor_onKeyguardGoingAway() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val argumentCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java) val argumentCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(argumentCaptor.capture()) verify(keyguardUpdateMonitor).registerCallback(argumentCaptor.capture())
@@ -184,9 +171,11 @@ class UserInteractorTest : SysuiTestCase() {
val lastValue = collectLastValue(underTest.dialogDismissRequests) val lastValue = collectLastValue(underTest.dialogDismissRequests)
assertNotNull(lastValue) assertNotNull(lastValue)
} }
}
@Test @Test
fun onRecordSelected_user() = fun onRecordSelected_user() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false) val userInfos = createUserInfos(count = 3, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -201,9 +190,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(activityManager).switchUser(userInfos[1].id) verify(activityManager).switchUser(userInfos[1].id)
Unit Unit
} }
}
@Test @Test
fun onRecordSelected_switchToGuestUser() = fun onRecordSelected_switchToGuestUser() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -217,9 +208,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(activityManager).switchUser(userInfos.last().id) verify(activityManager).switchUser(userInfos.last().id)
Unit Unit
} }
}
@Test @Test
fun onRecordSelected_switchToRestrictedUser() = fun onRecordSelected_switchToRestrictedUser() {
createUserInteractor()
testScope.runTest { testScope.runTest {
var userInfos = createUserInfos(count = 2, includeGuest = false).toMutableList() var userInfos = createUserInfos(count = 2, includeGuest = false).toMutableList()
userInfos.add( userInfos.add(
@@ -242,9 +235,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(activityManager).switchUser(userInfos.last().id) verify(activityManager).switchUser(userInfos.last().id)
Unit Unit
} }
}
@Test @Test
fun onRecordSelected_enterGuestMode() = fun onRecordSelected_enterGuestMode() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false) val userInfos = createUserInfos(count = 3, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -262,9 +257,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(manager).createGuest(any()) verify(manager).createGuest(any())
Unit Unit
} }
}
@Test @Test
fun onRecordSelected_action() = fun onRecordSelected_action() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -278,9 +275,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(dialogShower, never()).dismiss() verify(dialogShower, never()).dismiss()
verify(activityStarter).startActivity(any(), anyBoolean()) verify(activityStarter).startActivity(any(), anyBoolean())
} }
}
@Test @Test
fun users_switcherEnabled() = fun users_switcherEnabled() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -291,9 +290,11 @@ class UserInteractorTest : SysuiTestCase() {
assertUsers(models = value(), count = 3, includeGuest = true) assertUsers(models = value(), count = 3, includeGuest = true)
} }
}
@Test @Test
fun users_switchesToSecondUser() = fun users_switchesToSecondUser() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -305,9 +306,11 @@ class UserInteractorTest : SysuiTestCase() {
assertUsers(models = value(), count = 2, selectedIndex = 1) assertUsers(models = value(), count = 2, selectedIndex = 1)
} }
}
@Test @Test
fun users_switcherNotEnabled() = fun users_switcherNotEnabled() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -317,9 +320,11 @@ class UserInteractorTest : SysuiTestCase() {
val value = collectLastValue(underTest.users) val value = collectLastValue(underTest.users)
assertUsers(models = value(), count = 1) assertUsers(models = value(), count = 1)
} }
}
@Test @Test
fun selectedUser() = fun selectedUser() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -332,9 +337,11 @@ class UserInteractorTest : SysuiTestCase() {
userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSelectedUserInfo(userInfos[1])
assertUser(value(), id = 1, isSelected = true) assertUser(value(), id = 1, isSelected = true)
} }
}
@Test @Test
fun actions_deviceUnlocked() = fun actions_deviceUnlocked() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
@@ -356,9 +363,11 @@ class UserInteractorTest : SysuiTestCase() {
) )
) )
} }
}
@Test @Test
fun actions_deviceUnlocked_fullScreen() = fun actions_deviceUnlocked_fullScreen() {
createUserInteractor()
testScope.runTest { testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
@@ -379,9 +388,11 @@ class UserInteractorTest : SysuiTestCase() {
) )
) )
} }
}
@Test @Test
fun actions_deviceUnlockedUserNotPrimary_emptyList() = fun actions_deviceUnlockedUserNotPrimary_emptyList() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -392,9 +403,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(value()).isEqualTo(emptyList<UserActionModel>()) assertThat(value()).isEqualTo(emptyList<UserActionModel>())
} }
}
@Test @Test
fun actions_deviceUnlockedUserIsGuest_emptyList() = fun actions_deviceUnlockedUserIsGuest_emptyList() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = true) val userInfos = createUserInfos(count = 2, includeGuest = true)
assertThat(userInfos[1].isGuest).isTrue() assertThat(userInfos[1].isGuest).isTrue()
@@ -406,9 +419,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(value()).isEqualTo(emptyList<UserActionModel>()) assertThat(value()).isEqualTo(emptyList<UserActionModel>())
} }
}
@Test @Test
fun actions_deviceLockedAddFromLockscreenSet_fullList() = fun actions_deviceLockedAddFromLockscreenSet_fullList() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -432,9 +447,11 @@ class UserInteractorTest : SysuiTestCase() {
) )
) )
} }
}
@Test @Test
fun actions_deviceLockedAddFromLockscreenSet_fullList_fullScreen() = fun actions_deviceLockedAddFromLockscreenSet_fullList_fullScreen() {
createUserInteractor()
testScope.runTest { testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
@@ -459,9 +476,11 @@ class UserInteractorTest : SysuiTestCase() {
) )
) )
} }
}
@Test @Test
fun actions_deviceLocked_onlymanageUserIsShown() = fun actions_deviceLocked_onlymanageUserIsShown() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -472,9 +491,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(value()).isEqualTo(listOf(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)) assertThat(value()).isEqualTo(listOf(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT))
} }
}
@Test @Test
fun executeAction_addUser_dismissesDialogAndStartsActivity() = fun executeAction_addUser_dismissesDialogAndStartsActivity() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -486,9 +507,11 @@ class UserInteractorTest : SysuiTestCase() {
.log(MultiUserActionsEvent.CREATE_USER_FROM_USER_SWITCHER) .log(MultiUserActionsEvent.CREATE_USER_FROM_USER_SWITCHER)
underTest.onDialogShown() underTest.onDialogShown()
} }
}
@Test @Test
fun executeAction_addSupervisedUser_dismissesDialogAndStartsActivity() = fun executeAction_addSupervisedUser_dismissesDialogAndStartsActivity() {
createUserInteractor()
testScope.runTest { testScope.runTest {
underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER) underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER)
@@ -500,9 +523,11 @@ class UserInteractorTest : SysuiTestCase() {
.isEqualTo(UserManager.ACTION_CREATE_SUPERVISED_USER) .isEqualTo(UserManager.ACTION_CREATE_SUPERVISED_USER)
assertThat(intentCaptor.value.`package`).isEqualTo(SUPERVISED_USER_CREATION_APP_PACKAGE) assertThat(intentCaptor.value.`package`).isEqualTo(SUPERVISED_USER_CREATION_APP_PACKAGE)
} }
}
@Test @Test
fun executeAction_navigateToManageUsers() = fun executeAction_navigateToManageUsers() {
createUserInteractor()
testScope.runTest { testScope.runTest {
underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
@@ -510,9 +535,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(activityStarter).startActivity(intentCaptor.capture(), eq(true)) verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS) assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS)
} }
}
@Test @Test
fun executeAction_guestMode() = fun executeAction_guestMode() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -548,9 +575,11 @@ class UserInteractorTest : SysuiTestCase() {
) )
verify(activityManager).switchUser(guestUserInfo.id) verify(activityManager).switchUser(guestUserInfo.id)
} }
}
@Test @Test
fun selectUser_alreadySelectedGuestReSelected_exitGuestDialog() = fun selectUser_alreadySelectedGuestReSelected_exitGuestDialog() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = true) val userInfos = createUserInfos(count = 2, includeGuest = true)
val guestUserInfo = userInfos[1] val guestUserInfo = userInfos[1]
@@ -569,9 +598,11 @@ class UserInteractorTest : SysuiTestCase() {
.isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java) .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
verify(dialogShower, never()).dismiss() verify(dialogShower, never()).dismiss()
} }
}
@Test @Test
fun selectUser_currentlyGuestNonGuestSelected_exitGuestDialog() = fun selectUser_currentlyGuestNonGuestSelected_exitGuestDialog() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = true) val userInfos = createUserInfos(count = 2, includeGuest = true)
val guestUserInfo = userInfos[1] val guestUserInfo = userInfos[1]
@@ -587,9 +618,11 @@ class UserInteractorTest : SysuiTestCase() {
.isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java) .isInstanceOf(ShowDialogRequestModel.ShowExitGuestDialog::class.java)
verify(dialogShower, never()).dismiss() verify(dialogShower, never()).dismiss()
} }
}
@Test @Test
fun selectUser_notCurrentlyGuest_switchesUsers() = fun selectUser_notCurrentlyGuest_switchesUsers() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -603,9 +636,11 @@ class UserInteractorTest : SysuiTestCase() {
verify(activityManager).switchUser(userInfos[1].id) verify(activityManager).switchUser(userInfos[1].id)
verify(dialogShower).dismiss() verify(dialogShower).dismiss()
} }
}
@Test @Test
fun telephonyCallStateChanges_refreshesUsers() = fun telephonyCallStateChanges_refreshesUsers() {
createUserInteractor()
testScope.runTest { testScope.runTest {
runCurrent() runCurrent()
@@ -616,9 +651,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
} }
}
@Test @Test
fun userSwitchedBroadcast() = fun userSwitchedBroadcast() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -634,7 +671,7 @@ class UserInteractorTest : SysuiTestCase() {
userRepository.setSelectedUserInfo(userInfos[1]) userRepository.setSelectedUserInfo(userInfos[1])
runCurrent() runCurrent()
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context, spyContext,
Intent(Intent.ACTION_USER_SWITCHED) Intent(Intent.ACTION_USER_SWITCHED)
.putExtra(Intent.EXTRA_USER_HANDLE, userInfos[1].id), .putExtra(Intent.EXTRA_USER_HANDLE, userInfos[1].id),
) )
@@ -644,10 +681,13 @@ class UserInteractorTest : SysuiTestCase() {
verify(callback2, atLeastOnce()).onUserStateChanged() verify(callback2, atLeastOnce()).onUserStateChanged()
assertThat(userRepository.secondaryUserId).isEqualTo(userInfos[1].id) assertThat(userRepository.secondaryUserId).isEqualTo(userInfos[1].id)
assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
verify(spyContext).startServiceAsUser(any(), eq(UserHandle.of(userInfos[1].id)))
}
} }
@Test @Test
fun userInfoChangedBroadcast() = fun userInfoChangedBroadcast() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -655,7 +695,7 @@ class UserInteractorTest : SysuiTestCase() {
val refreshUsersCallCount = userRepository.refreshUsersCallCount val refreshUsersCallCount = userRepository.refreshUsersCallCount
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context, spyContext,
Intent(Intent.ACTION_USER_INFO_CHANGED), Intent(Intent.ACTION_USER_INFO_CHANGED),
) )
@@ -663,9 +703,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
} }
}
@Test @Test
fun systemUserUnlockedBroadcast_refreshUsers() = fun systemUserUnlockedBroadcast_refreshUsers() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -673,7 +715,7 @@ class UserInteractorTest : SysuiTestCase() {
val refreshUsersCallCount = userRepository.refreshUsersCallCount val refreshUsersCallCount = userRepository.refreshUsersCallCount
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context, spyContext,
Intent(Intent.ACTION_USER_UNLOCKED) Intent(Intent.ACTION_USER_UNLOCKED)
.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM), .putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM),
) )
@@ -681,9 +723,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1) assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
} }
}
@Test @Test
fun nonSystemUserUnlockedBroadcast_doNotRefreshUsers() = fun nonSystemUserUnlockedBroadcast_doNotRefreshUsers() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -691,15 +735,17 @@ class UserInteractorTest : SysuiTestCase() {
val refreshUsersCallCount = userRepository.refreshUsersCallCount val refreshUsersCallCount = userRepository.refreshUsersCallCount
fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
context, spyContext,
Intent(Intent.ACTION_USER_UNLOCKED).putExtra(Intent.EXTRA_USER_HANDLE, 1337), Intent(Intent.ACTION_USER_UNLOCKED).putExtra(Intent.EXTRA_USER_HANDLE, 1337),
) )
assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount) assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount)
} }
}
@Test @Test
fun userRecords() = fun userRecords() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false) val userInfos = createUserInfos(count = 3, includeGuest = false)
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
@@ -723,9 +769,11 @@ class UserInteractorTest : SysuiTestCase() {
), ),
) )
} }
}
@Test @Test
fun userRecordsFullScreen() = fun userRecordsFullScreen() {
createUserInteractor()
testScope.runTest { testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
val userInfos = createUserInfos(count = 3, includeGuest = false) val userInfos = createUserInfos(count = 3, includeGuest = false)
@@ -750,9 +798,11 @@ class UserInteractorTest : SysuiTestCase() {
), ),
) )
} }
}
@Test @Test
fun selectedUserRecord() = fun selectedUserRecord() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true)) userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
@@ -768,9 +818,11 @@ class UserInteractorTest : SysuiTestCase() {
isSwitchToEnabled = true, isSwitchToEnabled = true,
) )
} }
}
@Test @Test
fun users_secondaryUser_guestUserCanBeSwitchedTo() = fun users_secondaryUser_guestUserCanBeSwitchedTo() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -781,9 +833,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(res()?.size == 3).isTrue() assertThat(res()?.size == 3).isTrue()
assertThat(res()?.find { it.isGuest }).isNotNull() assertThat(res()?.find { it.isGuest }).isNotNull()
} }
}
@Test @Test
fun users_secondaryUser_noGuestAction() = fun users_secondaryUser_noGuestAction() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -793,9 +847,11 @@ class UserInteractorTest : SysuiTestCase() {
val res = collectLastValue(underTest.actions) val res = collectLastValue(underTest.actions)
assertThat(res()?.find { it == UserActionModel.ENTER_GUEST_MODE }).isNull() assertThat(res()?.find { it == UserActionModel.ENTER_GUEST_MODE }).isNull()
} }
}
@Test @Test
fun users_secondaryUser_noGuestUserRecord() = fun users_secondaryUser_noGuestUserRecord() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = true) val userInfos = createUserInfos(count = 3, includeGuest = true)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -804,9 +860,11 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(underTest.userRecords.value.find { it.isGuest }).isNull() assertThat(underTest.userRecords.value.find { it.isGuest }).isNull()
} }
}
@Test @Test
fun showUserSwitcher_fullScreenDisabled_showsDialogSwitcher() = fun showUserSwitcher_fullScreenDisabled_showsDialogSwitcher() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val expandable = mock<Expandable>() val expandable = mock<Expandable>()
underTest.showUserSwitcher(expandable) underTest.showUserSwitcher(expandable)
@@ -820,9 +878,11 @@ class UserInteractorTest : SysuiTestCase() {
underTest.onDialogShown() underTest.onDialogShown()
assertThat(dialogRequest()).isNull() assertThat(dialogRequest()).isNull()
} }
}
@Test @Test
fun showUserSwitcher_fullScreenEnabled_launchesFullScreenDialog() = fun showUserSwitcher_fullScreenEnabled_launchesFullScreenDialog() {
createUserInteractor()
testScope.runTest { testScope.runTest {
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
@@ -838,9 +898,11 @@ class UserInteractorTest : SysuiTestCase() {
underTest.onDialogShown() underTest.onDialogShown()
assertThat(dialogRequest()).isNull() assertThat(dialogRequest()).isNull()
} }
}
@Test @Test
fun users_secondaryUser_managedProfileIsNotIncluded() = fun users_secondaryUser_managedProfileIsNotIncluded() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList() val userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList()
userInfos.add( userInfos.add(
@@ -858,9 +920,11 @@ class UserInteractorTest : SysuiTestCase() {
val res = collectLastValue(underTest.users) val res = collectLastValue(underTest.users)
assertThat(res()?.size == 3).isTrue() assertThat(res()?.size == 3).isTrue()
} }
}
@Test @Test
fun currentUserIsNotPrimaryAndUserSwitcherIsDisabled() = fun currentUserIsNotPrimaryAndUserSwitcherIsDisabled() {
createUserInteractor()
testScope.runTest { testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false) val userInfos = createUserInfos(count = 2, includeGuest = false)
userRepository.setUserInfos(userInfos) userRepository.setUserInfos(userInfos)
@@ -869,9 +933,11 @@ class UserInteractorTest : SysuiTestCase() {
val selectedUser = collectLastValue(underTest.selectedUser) val selectedUser = collectLastValue(underTest.selectedUser)
assertThat(selectedUser()).isNotNull() assertThat(selectedUser()).isNotNull()
} }
}
@Test @Test
fun userRecords_isActionAndNoUsersUnlocked_actionIsDisabled() = fun userRecords_isActionAndNoUsersUnlocked_actionIsDisabled() {
createUserInteractor()
testScope.runTest { testScope.runTest {
keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardShowing(true)
whenever(manager.getUserSwitchability(any())) whenever(manager.getUserSwitchability(any()))
@@ -891,9 +957,11 @@ class UserInteractorTest : SysuiTestCase() {
.filter { it.info == null } .filter { it.info == null }
.forEach { action -> assertThat(action.isSwitchToEnabled).isFalse() } .forEach { action -> assertThat(action.isSwitchToEnabled).isFalse() }
} }
}
@Test @Test
fun userRecords_isActionAndNoUsersUnlocked_actionIsDisabled_HeadlessMode() = fun userRecords_isActionAndNoUsersUnlocked_actionIsDisabled_HeadlessMode() {
createUserInteractor()
testScope.runTest { testScope.runTest {
keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardShowing(true)
whenever(headlessSystemUserMode.isHeadlessSystemUserMode()).thenReturn(true) whenever(headlessSystemUserMode.isHeadlessSystemUserMode()).thenReturn(true)
@@ -913,6 +981,7 @@ class UserInteractorTest : SysuiTestCase() {
.filter { it.info == null } .filter { it.info == null }
.forEach { action -> assertThat(action.isSwitchToEnabled).isFalse() } .forEach { action -> assertThat(action.isSwitchToEnabled).isFalse() }
} }
}
private fun assertUsers( private fun assertUsers(
models: List<UserModel>?, models: List<UserModel>?,
@@ -1005,6 +1074,53 @@ class UserInteractorTest : SysuiTestCase() {
.isEqualTo(type == UserActionModel.ADD_SUPERVISED_USER) .isEqualTo(type == UserActionModel.ADD_SUPERVISED_USER)
} }
private fun createUserInteractor(startAsProcessUser: Boolean = true) {
val processUserId = Process.myUserHandle().identifier
val startUserId = if (startAsProcessUser) processUserId else (processUserId + 1)
runBlocking {
val userInfo =
createUserInfo(id = startUserId, name = "user_$startUserId", isPrimary = true)
userRepository.setUserInfos(listOf(userInfo))
userRepository.setSelectedUserInfo(userInfo)
}
underTest =
UserInteractor(
applicationContext = spyContext,
repository = userRepository,
activityStarter = activityStarter,
keyguardInteractor = keyguardReply.keyguardInteractor,
manager = manager,
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
repository = telephonyRepository,
),
broadcastDispatcher = fakeBroadcastDispatcher,
keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor =
GuestUserInteractor(
applicationContext = spyContext,
applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher,
backgroundDispatcher = testDispatcher,
manager = manager,
repository = userRepository,
deviceProvisionedController = deviceProvisionedController,
devicePolicyManager = devicePolicyManager,
refreshUsersScheduler = refreshUsersScheduler,
uiEventLogger = uiEventLogger,
resumeSessionReceiver = resumeSessionReceiver,
resetOrExitSessionReceiver = resetOrExitSessionReceiver,
),
uiEventLogger = uiEventLogger,
featureFlags = featureFlags,
)
}
private fun createUserInfos( private fun createUserInfos(
count: Int, count: Int,
includeGuest: Boolean, includeGuest: Boolean,

View File

@@ -50,6 +50,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.advanceUntilIdle
@@ -237,6 +238,10 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
set(Flags.FULL_SCREEN_USER_SWITCHER, false) set(Flags.FULL_SCREEN_USER_SWITCHER, false)
set(Flags.FACE_AUTH_REFACTOR, true) set(Flags.FACE_AUTH_REFACTOR, true)
} }
runBlocking {
userRepository.setUserInfos(listOf(USER_0))
userRepository.setSelectedUserInfo(USER_0)
}
return StatusBarUserChipViewModel( return StatusBarUserChipViewModel(
context = context, context = context,
interactor = interactor =

View File

@@ -102,6 +102,20 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
testScope = TestScope(testDispatcher) testScope = TestScope(testDispatcher)
userRepository = FakeUserRepository() userRepository = FakeUserRepository()
runBlocking { runBlocking {
val userInfos =
listOf(
UserInfo(
/* id= */ 0,
/* name= */ "zero",
/* iconPath= */ "",
/* flags= */ UserInfo.FLAG_PRIMARY or
UserInfo.FLAG_ADMIN or
UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_SYSTEM,
),
)
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[0])
userRepository.setSettings( userRepository.setSettings(
UserSwitcherSettingsModel( UserSwitcherSettingsModel(
isUserSwitcherEnabled = true, isUserSwitcherEnabled = true,