summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tetiana Meronyk <tetianameronyk@google.com> 2023-02-13 23:39:52 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-02-13 23:39:52 +0000
commitc0511060f42e4530d82747afa5d0cd9a34e0fd43 (patch)
tree5de1a3f6f2c9a2a9e8da21d1b143aabe600c5541
parent090f8dca9cdfe21e64aa3f0b2e92680da6fb899f (diff)
parentf4f93d0ea95fd0f1052a8cd96ba9c53644120576 (diff)
Merge "Prevent adding a user from lockscreen until a user has signed in" into tm-qpr-dev
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/UserModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserMode.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserModeModule.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt47
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt3
7 files changed, 144 insertions, 6 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserModule.java b/packages/SystemUI/src/com/android/systemui/user/UserModule.java
index 2b29885db682..f7c8bac1b478 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserModule.java
+++ b/packages/SystemUI/src/com/android/systemui/user/UserModule.java
@@ -21,6 +21,7 @@ import android.os.UserHandle;
import com.android.settingslib.users.EditUserInfoController;
import com.android.systemui.user.data.repository.UserRepositoryModule;
+import com.android.systemui.user.domain.interactor.HeadlessSystemUserModeModule;
import com.android.systemui.user.ui.dialog.UserDialogModule;
import dagger.Binds;
@@ -36,6 +37,7 @@ import dagger.multibindings.IntoMap;
includes = {
UserDialogModule.class,
UserRepositoryModule.class,
+ HeadlessSystemUserModeModule.class,
}
)
public abstract class UserModule {
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserMode.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserMode.kt
new file mode 100644
index 000000000000..756e6a1a5b15
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserMode.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.user.domain.interactor
+
+import android.os.UserManager
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+interface HeadlessSystemUserMode {
+
+ fun isHeadlessSystemUserMode(): Boolean
+}
+
+@SysUISingleton
+class HeadlessSystemUserModeImpl @Inject constructor() : HeadlessSystemUserMode {
+ override fun isHeadlessSystemUserMode(): Boolean {
+ return UserManager.isHeadlessSystemUserMode()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserModeModule.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserModeModule.kt
new file mode 100644
index 000000000000..0efa2d8b6a36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/HeadlessSystemUserModeModule.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 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.user.domain.interactor
+
+import dagger.Binds
+
+@dagger.Module
+interface HeadlessSystemUserModeModule {
+
+ @Binds
+ fun bindIsHeadlessSystemUserMode(impl: HeadlessSystemUserModeImpl): HeadlessSystemUserMode
+}
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index c0ba3cc352b0..3f895ad0b5b4 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -86,6 +86,7 @@ constructor(
private val keyguardInteractor: KeyguardInteractor,
private val featureFlags: FeatureFlags,
private val manager: UserManager,
+ private val headlessSystemUserMode: HeadlessSystemUserMode,
@Application private val applicationScope: CoroutineScope,
telephonyInteractor: TelephonyInteractor,
broadcastDispatcher: BroadcastDispatcher,
@@ -560,7 +561,10 @@ constructor(
actionType = action,
isRestricted = isRestricted,
isSwitchToEnabled =
- canSwitchUsers(selectedUserId) &&
+ canSwitchUsers(
+ selectedUserId = selectedUserId,
+ isAction = true,
+ ) &&
// If the user is auto-created is must not be currently resetting.
!(isGuestUserAutoCreated && isGuestUserResetting),
)
@@ -712,10 +716,32 @@ constructor(
}
}
- private suspend fun canSwitchUsers(selectedUserId: Int): Boolean {
- return withContext(backgroundDispatcher) {
- manager.getUserSwitchability(UserHandle.of(selectedUserId))
- } == UserManager.SWITCHABILITY_STATUS_OK
+ 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
+ // signed in since reboot or in all cases for non-headless system user mode.
+ val isItemEnabled = !isAction || !isHeadlessSystemUserMode || isAnyUserUnlocked()
+ return isItemEnabled &&
+ withContext(backgroundDispatcher) {
+ manager.getUserSwitchability(UserHandle.of(selectedUserId))
+ } == UserManager.SWITCHABILITY_STATUS_OK
+ }
+
+ private suspend fun isAnyUserUnlocked(): Boolean {
+ return manager
+ .getUsers(
+ /* excludePartial= */ true,
+ /* excludeDying= */ true,
+ /* excludePreCreated= */ true
+ )
+ .any { user ->
+ user.id != UserHandle.USER_SYSTEM &&
+ withContext(backgroundDispatcher) { manager.isUserUnlocked(user.userHandle) }
+ }
}
@SuppressLint("UseCompatLoadingForDrawables")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index 8660d097c0df..0257ebd5c6d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -28,7 +28,6 @@ import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
import androidx.test.filters.SmallTest
-import com.android.internal.R.drawable.ic_account_circle
import com.android.internal.logging.UiEventLogger
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
@@ -87,6 +86,7 @@ class UserInteractorTest : SysuiTestCase() {
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var manager: UserManager
+ @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
@Mock private lateinit var activityManager: ActivityManager
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@@ -145,6 +145,7 @@ class UserInteractorTest : SysuiTestCase() {
featureFlags = featureFlags,
),
manager = manager,
+ headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
@@ -848,6 +849,50 @@ class UserInteractorTest : SysuiTestCase() {
assertThat(selectedUser()).isNotNull()
}
+ @Test
+ fun userRecords_isActionAndNoUsersUnlocked_actionIsDisabled() =
+ testScope.runTest {
+ keyguardRepository.setKeyguardShowing(true)
+ whenever(manager.getUserSwitchability(any()))
+ .thenReturn(UserManager.SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED)
+ val userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList()
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[1])
+ userRepository.setSettings(
+ UserSwitcherSettingsModel(
+ isUserSwitcherEnabled = true,
+ isAddUsersFromLockscreen = true
+ )
+ )
+
+ runCurrent()
+ underTest.userRecords.value
+ .filter { it.info == null }
+ .forEach { action -> assertThat(action.isSwitchToEnabled).isFalse() }
+ }
+
+ @Test
+ fun userRecords_isActionAndNoUsersUnlocked_actionIsDisabled_HeadlessMode() =
+ testScope.runTest {
+ keyguardRepository.setKeyguardShowing(true)
+ whenever(headlessSystemUserMode.isHeadlessSystemUserMode()).thenReturn(true)
+ whenever(manager.isUserUnlocked(anyInt())).thenReturn(false)
+ val userInfos = createUserInfos(count = 3, includeGuest = false).toMutableList()
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[1])
+ userRepository.setSettings(
+ UserSwitcherSettingsModel(
+ isUserSwitcherEnabled = true,
+ isAddUsersFromLockscreen = true
+ )
+ )
+
+ runCurrent()
+ underTest.userRecords.value
+ .filter { it.info == null }
+ .forEach { action -> assertThat(action.isSwitchToEnabled).isFalse() }
+ }
+
private fun assertUsers(
models: List<UserModel>?,
count: Int,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 8a35cb05038a..2fedb875b3e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -41,6 +41,7 @@ import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.domain.interactor.GuestUserInteractor
+import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.util.mockito.mock
@@ -71,6 +72,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var activityManager: ActivityManager
@Mock private lateinit var manager: UserManager
+ @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var uiEventLogger: UiEventLogger
@@ -252,6 +254,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
),
featureFlags = featureFlags,
manager = manager,
+ headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 1337d1bdb7ca..166b90943847 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -41,6 +41,7 @@ import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.domain.interactor.GuestUserInteractor
+import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
@@ -72,6 +73,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var activityManager: ActivityManager
@Mock private lateinit var manager: UserManager
+ @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var uiEventLogger: UiEventLogger
@@ -154,6 +156,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
),
featureFlags = featureFlags,
manager = manager,
+ headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(