[Bouncer] Add manage users to bouncer.
Add a manage users option to the user switcher for the Bouncer. This adds a isMangeUsers property to the UserRecord and makes some changes around that. If user is on bouncer while trying to go to manage users or add a child user, bouncer will show a message to indicate that user needs to unlock the device in order to proceed. Bug: 241811308 Test: Added a unit test and manual test. Manual test consists of testing with new userswitcher code flag on and off, testing non fullscreen user switcher, user switcher activity, and user switcher in the bouncer. In addition to testing the manage users. I've added the max number of users and tested add user and add child user. I also tested scenarios where we click on manage users and then exit bouncer. Change-Id: Ib20c32914fd95eb891676028b5b588009b9e50a6
This commit is contained in:
@@ -241,4 +241,6 @@
|
||||
<string name="clock_title_bubble">Bubble</string>
|
||||
<!-- Name of the "Analog" clock face [CHAR LIMIT=15]-->
|
||||
<string name="clock_title_analog">Analog</string>
|
||||
<!-- Title of bouncer when we want to authenticate before continuing with action. [CHAR LIMIT=NONE] -->
|
||||
<string name="keyguard_unlock_to_continue">Unlock your device to continue</string>
|
||||
</resources>
|
||||
|
||||
@@ -67,7 +67,6 @@ import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowInsetsAnimation;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@@ -318,7 +317,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
}
|
||||
|
||||
void initMode(@Mode int mode, GlobalSettings globalSettings, FalsingManager falsingManager,
|
||||
UserSwitcherController userSwitcherController) {
|
||||
UserSwitcherController userSwitcherController,
|
||||
UserSwitcherViewMode.UserSwitcherCallback userSwitcherCallback) {
|
||||
if (mCurrentMode == mode) return;
|
||||
Log.i(TAG, "Switching mode from " + modeToString(mCurrentMode) + " to "
|
||||
+ modeToString(mode));
|
||||
@@ -330,7 +330,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
mViewMode = new OneHandedViewMode();
|
||||
break;
|
||||
case MODE_USER_SWITCHER:
|
||||
mViewMode = new UserSwitcherViewMode();
|
||||
mViewMode = new UserSwitcherViewMode(userSwitcherCallback);
|
||||
break;
|
||||
default:
|
||||
mViewMode = new DefaultViewMode();
|
||||
@@ -864,6 +864,12 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
private UserSwitcherController.UserSwitchCallback mUserSwitchCallback =
|
||||
this::setupUserSwitcher;
|
||||
|
||||
private UserSwitcherCallback mUserSwitcherCallback;
|
||||
|
||||
UserSwitcherViewMode(UserSwitcherCallback userSwitcherCallback) {
|
||||
mUserSwitcherCallback = userSwitcherCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@NonNull ConstraintLayout v, @NonNull GlobalSettings globalSettings,
|
||||
@NonNull KeyguardSecurityViewFlipper viewFlipper,
|
||||
@@ -1040,34 +1046,25 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
}
|
||||
};
|
||||
|
||||
if (adapter.getCount() < 2) {
|
||||
// The drop down arrow is at index 1
|
||||
((LayerDrawable) mUserSwitcher.getBackground()).getDrawable(1).setAlpha(0);
|
||||
anchor.setClickable(false);
|
||||
return;
|
||||
} else {
|
||||
((LayerDrawable) mUserSwitcher.getBackground()).getDrawable(1).setAlpha(255);
|
||||
}
|
||||
|
||||
anchor.setOnClickListener((v) -> {
|
||||
if (mFalsingManager.isFalseTap(LOW_PENALTY)) return;
|
||||
mPopup = new KeyguardUserSwitcherPopupMenu(v.getContext(), mFalsingManager);
|
||||
mPopup.setAnchorView(anchor);
|
||||
mPopup.setAdapter(adapter);
|
||||
mPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView parent, View view, int pos, long id) {
|
||||
if (mFalsingManager.isFalseTap(LOW_PENALTY)) return;
|
||||
if (!view.isEnabled()) return;
|
||||
|
||||
// Subtract one for the header
|
||||
UserRecord user = adapter.getItem(pos - 1);
|
||||
if (!user.isCurrent) {
|
||||
adapter.onUserListItemClicked(user);
|
||||
}
|
||||
mPopup.dismiss();
|
||||
mPopup = null;
|
||||
}
|
||||
});
|
||||
mPopup.setOnItemClickListener((parent, view, pos, id) -> {
|
||||
if (mFalsingManager.isFalseTap(LOW_PENALTY)) return;
|
||||
if (!view.isEnabled()) return;
|
||||
// Subtract one for the header
|
||||
UserRecord user = adapter.getItem(pos - 1);
|
||||
if (user.isManageUsers || user.isAddSupervisedUser) {
|
||||
mUserSwitcherCallback.showUnlockToContinueMessage();
|
||||
}
|
||||
if (!user.isCurrent) {
|
||||
adapter.onUserListItemClicked(user);
|
||||
}
|
||||
mPopup.dismiss();
|
||||
mPopup = null;
|
||||
});
|
||||
mPopup.show();
|
||||
});
|
||||
}
|
||||
@@ -1122,6 +1119,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
constraintSet.applyTo(mView);
|
||||
}
|
||||
}
|
||||
|
||||
interface UserSwitcherCallback {
|
||||
void showUnlockToContinueMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -620,7 +620,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
mode = KeyguardSecurityContainer.MODE_ONE_HANDED;
|
||||
}
|
||||
|
||||
mView.initMode(mode, mGlobalSettings, mFalsingManager, mUserSwitcherController);
|
||||
mView.initMode(mode, mGlobalSettings, mFalsingManager, mUserSwitcherController,
|
||||
() -> showMessage(getContext().getString(R.string.keyguard_unlock_to_continue),
|
||||
null));
|
||||
}
|
||||
|
||||
public void reportFailedUnlockAttempt(int userId, int timeoutMs) {
|
||||
|
||||
@@ -35,8 +35,8 @@ protected constructor(
|
||||
protected val controller: UserSwitcherController,
|
||||
) : BaseAdapter() {
|
||||
|
||||
protected open val users: ArrayList<UserRecord>
|
||||
get() = controller.users
|
||||
protected open val users: List<UserRecord>
|
||||
get() = controller.users.filter { !controller.isKeyguardShowing || !it.isRestricted }
|
||||
|
||||
init {
|
||||
controller.addAdapter(WeakReference(this))
|
||||
@@ -112,6 +112,7 @@ protected constructor(
|
||||
item.isGuest,
|
||||
item.isAddSupervisedUser,
|
||||
isTablet,
|
||||
item.isManageUsers,
|
||||
)
|
||||
return checkNotNull(context.getDrawable(iconRes))
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.android.systemui.user.data.source.UserRecord;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -456,7 +457,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
|
||||
}
|
||||
|
||||
void refreshUserOrder() {
|
||||
ArrayList<UserRecord> users = super.getUsers();
|
||||
List<UserRecord> users = super.getUsers();
|
||||
mUsersOrdered = new ArrayList<>(users.size());
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
UserRecord record = users.get(i);
|
||||
|
||||
@@ -249,7 +249,7 @@ constructor(
|
||||
|
||||
override fun startActivity(intent: Intent) {
|
||||
if (useInteractor) {
|
||||
activityStarter.startActivity(intent, /* dismissShade= */ false)
|
||||
activityStarter.startActivity(intent, /* dismissShade= */ true)
|
||||
} else {
|
||||
_oldImpl.startActivity(intent)
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.settingslib.users.UserCreatingDialog;
|
||||
import com.android.systemui.GuestResetOrExitSessionReceiver;
|
||||
import com.android.systemui.GuestResumeSessionReceiver;
|
||||
@@ -399,6 +400,16 @@ public class UserSwitcherControllerOldImpl implements UserSwitcherController {
|
||||
records.add(userRecord);
|
||||
}
|
||||
|
||||
if (canManageUsers()) {
|
||||
records.add(LegacyUserDataHelper.createRecord(
|
||||
mContext,
|
||||
KeyguardUpdateMonitor.getCurrentUser(),
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
/* isRestricted= */ false,
|
||||
/* isSwitchToEnabled= */ true
|
||||
));
|
||||
}
|
||||
|
||||
mUiExecutor.execute(() -> {
|
||||
if (records != null) {
|
||||
mUsers = records;
|
||||
@@ -438,6 +449,14 @@ public class UserSwitcherControllerOldImpl implements UserSwitcherController {
|
||||
&& mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean canManageUsers() {
|
||||
UserInfo currentUser = mUserTracker.getUserInfo();
|
||||
return mUserSwitcherEnabled
|
||||
&& ((currentUser != null && currentUser.isAdmin())
|
||||
|| mAddUsersFromLockScreen.getValue());
|
||||
}
|
||||
|
||||
private boolean createIsRestricted() {
|
||||
return !mAddUsersFromLockScreen.getValue();
|
||||
}
|
||||
@@ -525,6 +544,8 @@ public class UserSwitcherControllerOldImpl implements UserSwitcherController {
|
||||
showAddUserDialog(dialogShower);
|
||||
} else if (record.isAddSupervisedUser) {
|
||||
startSupervisedUserActivity();
|
||||
} else if (record.isManageUsers) {
|
||||
startActivity(new Intent(Settings.ACTION_USER_SETTINGS));
|
||||
} else {
|
||||
onUserListItemClicked(record.info.id, record, dialogShower);
|
||||
}
|
||||
@@ -984,7 +1005,7 @@ public class UserSwitcherControllerOldImpl implements UserSwitcherController {
|
||||
|
||||
@Override
|
||||
public void startActivity(Intent intent) {
|
||||
mActivityStarter.startActivity(intent, true);
|
||||
mActivityStarter.startActivity(intent, /* dismissShade= */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,6 +47,9 @@ data class UserRecord(
|
||||
* If not disabled, this is `null`.
|
||||
*/
|
||||
@JvmField val enforcedAdmin: RestrictedLockUtils.EnforcedAdmin? = null,
|
||||
|
||||
/** Whether this record is to go to the Settings page to manage users. */
|
||||
@JvmField val isManageUsers: Boolean = false
|
||||
) {
|
||||
/** Returns a new instance of [UserRecord] with its [isCurrent] set to the given value. */
|
||||
fun copyWithIsCurrent(isCurrent: Boolean): UserRecord {
|
||||
|
||||
@@ -82,6 +82,15 @@ object UserActionsUtil {
|
||||
)
|
||||
}
|
||||
|
||||
fun canManageUsers(
|
||||
repository: UserRepository,
|
||||
isUserSwitcherEnabled: Boolean,
|
||||
isAddUsersFromLockScreenEnabled: Boolean,
|
||||
): Boolean {
|
||||
return isUserSwitcherEnabled &&
|
||||
(repository.getSelectedUserInfo().isAdmin || isAddUsersFromLockScreenEnabled)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the current user is allowed to add users to the device; `false` otherwise.
|
||||
*/
|
||||
|
||||
@@ -102,6 +102,7 @@ constructor(
|
||||
interface UserCallback {
|
||||
/** Returns `true` if this callback can be cleaned-up. */
|
||||
fun isEvictable(): Boolean = false
|
||||
|
||||
/** Notifies that the state of users on the device has changed. */
|
||||
fun onUserStateChanged()
|
||||
}
|
||||
@@ -164,10 +165,11 @@ constructor(
|
||||
get() =
|
||||
if (isNewImpl) {
|
||||
combine(
|
||||
repository.selectedUserInfo,
|
||||
repository.userInfos,
|
||||
repository.userSwitcherSettings,
|
||||
keyguardInteractor.isKeyguardShowing,
|
||||
) { userInfos, settings, isDeviceLocked ->
|
||||
) { _, userInfos, settings, isDeviceLocked ->
|
||||
buildList {
|
||||
val hasGuestUser = userInfos.any { it.isGuest }
|
||||
if (
|
||||
@@ -183,35 +185,45 @@ constructor(
|
||||
add(UserActionModel.ENTER_GUEST_MODE)
|
||||
}
|
||||
|
||||
if (isDeviceLocked && !settings.isAddUsersFromLockscreen) {
|
||||
if (!isDeviceLocked || settings.isAddUsersFromLockscreen) {
|
||||
// The device is locked and our setting to allow actions that add users
|
||||
// from the lock-screen is not enabled. The guest action from above is
|
||||
// always allowed, even when the device is locked, but the various "add
|
||||
// user" actions below are not. We can finish building the list here.
|
||||
return@buildList
|
||||
|
||||
val canCreateUsers =
|
||||
UserActionsUtil.canCreateUser(
|
||||
manager,
|
||||
repository,
|
||||
settings.isUserSwitcherEnabled,
|
||||
settings.isAddUsersFromLockscreen,
|
||||
)
|
||||
|
||||
if (canCreateUsers) {
|
||||
add(UserActionModel.ADD_USER)
|
||||
}
|
||||
|
||||
if (
|
||||
UserActionsUtil.canCreateSupervisedUser(
|
||||
manager,
|
||||
repository,
|
||||
settings.isUserSwitcherEnabled,
|
||||
settings.isAddUsersFromLockscreen,
|
||||
supervisedUserPackageName,
|
||||
)
|
||||
) {
|
||||
add(UserActionModel.ADD_SUPERVISED_USER)
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
UserActionsUtil.canCreateUser(
|
||||
manager,
|
||||
UserActionsUtil.canManageUsers(
|
||||
repository,
|
||||
settings.isUserSwitcherEnabled,
|
||||
settings.isAddUsersFromLockscreen,
|
||||
)
|
||||
) {
|
||||
add(UserActionModel.ADD_USER)
|
||||
}
|
||||
|
||||
if (
|
||||
UserActionsUtil.canCreateSupervisedUser(
|
||||
manager,
|
||||
repository,
|
||||
settings.isUserSwitcherEnabled,
|
||||
settings.isAddUsersFromLockscreen,
|
||||
supervisedUserPackageName,
|
||||
)
|
||||
) {
|
||||
add(UserActionModel.ADD_SUPERVISED_USER)
|
||||
add(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,7 +276,10 @@ constructor(
|
||||
toRecord(
|
||||
action = it,
|
||||
selectedUserId = selectedUserInfo.id,
|
||||
isAddFromLockscreenEnabled = settings.isAddUsersFromLockscreen,
|
||||
isRestricted =
|
||||
it != UserActionModel.ENTER_GUEST_MODE &&
|
||||
it != UserActionModel.NAVIGATE_TO_USER_MANAGEMENT &&
|
||||
!settings.isAddUsersFromLockscreen,
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -482,12 +497,12 @@ constructor(
|
||||
.setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
|
||||
.setPackage(supervisedUserPackageName)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
|
||||
/* dismissShade= */ false,
|
||||
/* dismissShade= */ true,
|
||||
)
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT ->
|
||||
activityStarter.startActivity(
|
||||
Intent(Settings.ACTION_USER_SETTINGS),
|
||||
/* dismissShade= */ false,
|
||||
/* dismissShade= */ true,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -575,20 +590,13 @@ constructor(
|
||||
private suspend fun toRecord(
|
||||
action: UserActionModel,
|
||||
selectedUserId: Int,
|
||||
isAddFromLockscreenEnabled: Boolean,
|
||||
isRestricted: Boolean,
|
||||
): UserRecord {
|
||||
return LegacyUserDataHelper.createRecord(
|
||||
context = applicationContext,
|
||||
selectedUserId = selectedUserId,
|
||||
actionType = action,
|
||||
isRestricted =
|
||||
if (action == UserActionModel.ENTER_GUEST_MODE) {
|
||||
// Entering guest mode is never restricted, so it's allowed to happen from the
|
||||
// lockscreen even if the "add from lockscreen" system setting is off.
|
||||
false
|
||||
} else {
|
||||
!isAddFromLockscreenEnabled
|
||||
},
|
||||
isRestricted = isRestricted,
|
||||
isSwitchToEnabled =
|
||||
canSwitchUsers(selectedUserId) &&
|
||||
// If the user is auto-created is must not be currently resetting.
|
||||
|
||||
@@ -80,6 +80,7 @@ object LegacyUserDataHelper {
|
||||
context = context,
|
||||
selectedUserId = selectedUserId,
|
||||
),
|
||||
isManageUsers = actionType == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -90,6 +91,7 @@ object LegacyUserDataHelper {
|
||||
record.isAddUser -> UserActionModel.ADD_USER
|
||||
record.isAddSupervisedUser -> UserActionModel.ADD_SUPERVISED_USER
|
||||
record.isGuest -> UserActionModel.ENTER_GUEST_MODE
|
||||
record.isManageUsers -> UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
|
||||
else -> error("Not a known action: $record")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ object LegacyUserUiHelper {
|
||||
isGuest: Boolean,
|
||||
isAddSupervisedUser: Boolean,
|
||||
isTablet: Boolean = false,
|
||||
isManageUsers: Boolean,
|
||||
): Int {
|
||||
return if (isAddUser && isTablet) {
|
||||
R.drawable.ic_account_circle_filled
|
||||
@@ -48,6 +49,8 @@ object LegacyUserUiHelper {
|
||||
R.drawable.ic_account_circle
|
||||
} else if (isAddSupervisedUser) {
|
||||
R.drawable.ic_add_supervised_user
|
||||
} else if (isManageUsers) {
|
||||
R.drawable.ic_manage_users
|
||||
} else {
|
||||
R.drawable.ic_avatar_user
|
||||
}
|
||||
@@ -74,6 +77,7 @@ object LegacyUserUiHelper {
|
||||
isAddUser = record.isAddUser,
|
||||
isAddSupervisedUser = record.isAddSupervisedUser,
|
||||
isTablet = isTablet,
|
||||
isManageUsers = record.isManageUsers,
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -103,8 +107,9 @@ object LegacyUserUiHelper {
|
||||
isAddUser: Boolean,
|
||||
isAddSupervisedUser: Boolean,
|
||||
isTablet: Boolean = false,
|
||||
isManageUsers: Boolean,
|
||||
): Int {
|
||||
check(isGuest || isAddUser || isAddSupervisedUser)
|
||||
check(isGuest || isAddUser || isAddSupervisedUser || isManageUsers)
|
||||
|
||||
return when {
|
||||
isGuest && isGuestUserAutoCreated && isGuestUserResetting ->
|
||||
@@ -114,6 +119,7 @@ object LegacyUserUiHelper {
|
||||
isGuest -> com.android.internal.R.string.guest_name
|
||||
isAddUser -> com.android.settingslib.R.string.user_add_user
|
||||
isAddSupervisedUser -> R.string.add_user_supervised
|
||||
isManageUsers -> R.string.manage_users
|
||||
else -> error("This should never happen!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ package com.android.systemui.user.ui.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.common.shared.model.Text
|
||||
import com.android.systemui.common.ui.drawable.CircularDrawable
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
@@ -162,12 +160,7 @@ private constructor(
|
||||
): UserViewModel {
|
||||
return UserViewModel(
|
||||
viewKey = model.id,
|
||||
name =
|
||||
if (model.isGuest) {
|
||||
Text.Resource(com.android.settingslib.R.string.guest_exit_quick_settings_button)
|
||||
} else {
|
||||
model.name
|
||||
},
|
||||
name = model.name,
|
||||
image = CircularDrawable(model.image),
|
||||
isSelectionMarkerVisible = model.isSelected,
|
||||
alpha =
|
||||
@@ -186,29 +179,23 @@ private constructor(
|
||||
return UserActionViewModel(
|
||||
viewKey = model.ordinal.toLong(),
|
||||
iconResourceId =
|
||||
if (model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) {
|
||||
R.drawable.ic_manage_users
|
||||
} else {
|
||||
LegacyUserUiHelper.getUserSwitcherActionIconResourceId(
|
||||
isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER,
|
||||
isAddUser = model == UserActionModel.ADD_USER,
|
||||
isGuest = model == UserActionModel.ENTER_GUEST_MODE,
|
||||
isTablet = true,
|
||||
)
|
||||
},
|
||||
LegacyUserUiHelper.getUserSwitcherActionIconResourceId(
|
||||
isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER,
|
||||
isAddUser = model == UserActionModel.ADD_USER,
|
||||
isGuest = model == UserActionModel.ENTER_GUEST_MODE,
|
||||
isManageUsers = model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
isTablet = true,
|
||||
),
|
||||
textResourceId =
|
||||
if (model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) {
|
||||
R.string.manage_users
|
||||
} else {
|
||||
LegacyUserUiHelper.getUserSwitcherActionTextResourceId(
|
||||
isGuest = model == UserActionModel.ENTER_GUEST_MODE,
|
||||
isGuestUserAutoCreated = guestUserInteractor.isGuestUserAutoCreated,
|
||||
isGuestUserResetting = guestUserInteractor.isGuestUserResetting,
|
||||
isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER,
|
||||
isAddUser = model == UserActionModel.ADD_USER,
|
||||
isTablet = true,
|
||||
)
|
||||
},
|
||||
LegacyUserUiHelper.getUserSwitcherActionTextResourceId(
|
||||
isGuest = model == UserActionModel.ENTER_GUEST_MODE,
|
||||
isGuestUserAutoCreated = guestUserInteractor.isGuestUserAutoCreated,
|
||||
isGuestUserResetting = guestUserInteractor.isGuestUserResetting,
|
||||
isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER,
|
||||
isAddUser = model == UserActionModel.ADD_USER,
|
||||
isManageUsers = model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
isTablet = true,
|
||||
),
|
||||
onClicked = {
|
||||
userInteractor.executeAction(action = model)
|
||||
// We don't finish because we want to show a dialog over the full-screen UI and
|
||||
|
||||
@@ -221,15 +221,17 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
public void onResourcesUpdate_callsThroughOnRotationChange() {
|
||||
// Rotation is the same, shouldn't cause an update
|
||||
mKeyguardSecurityContainerController.updateResources();
|
||||
verify(mView, never()).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
verify(mView, never()).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
|
||||
eq(mUserSwitcherController),
|
||||
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class));
|
||||
|
||||
// Update rotation. Should trigger update
|
||||
mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
|
||||
|
||||
mKeyguardSecurityContainerController.updateResources();
|
||||
verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
|
||||
eq(mUserSwitcherController),
|
||||
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class));
|
||||
}
|
||||
|
||||
private void touchDown() {
|
||||
@@ -263,8 +265,9 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
|
||||
|
||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
|
||||
verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
|
||||
eq(mUserSwitcherController),
|
||||
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -275,8 +278,9 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
|
||||
|
||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
|
||||
verify(mView).initMode(MODE_ONE_HANDED, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
verify(mView).initMode(eq(MODE_ONE_HANDED), eq(mGlobalSettings), eq(mFalsingManager),
|
||||
eq(mUserSwitcherController),
|
||||
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -285,8 +289,26 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
setupGetSecurityView();
|
||||
|
||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
|
||||
verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
|
||||
eq(mUserSwitcherController),
|
||||
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addUserSwitcherCallback() {
|
||||
ArgumentCaptor<KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback>
|
||||
captor = ArgumentCaptor.forClass(
|
||||
KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class);
|
||||
|
||||
setupGetSecurityView();
|
||||
|
||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
|
||||
verify(mView).initMode(anyInt(), any(GlobalSettings.class), any(FalsingManager.class),
|
||||
any(UserSwitcherController.class),
|
||||
captor.capture());
|
||||
captor.getValue().showUnlockToContinueMessage();
|
||||
verify(mKeyguardPasswordViewControllerMock).showMessage(
|
||||
getContext().getString(R.string.keyguard_unlock_to_continue), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -119,7 +119,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
int systemBarInsetAmount = 0;
|
||||
|
||||
mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
mUserSwitcherController, () -> {});
|
||||
|
||||
Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
|
||||
Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
|
||||
@@ -141,7 +141,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
int systemBarInsetAmount = paddingBottom + 1;
|
||||
|
||||
mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
mUserSwitcherController, () -> {});
|
||||
|
||||
Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
|
||||
Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
|
||||
@@ -158,9 +158,10 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testDefaultViewMode() {
|
||||
mKeyguardSecurityContainer.initMode(MODE_ONE_HANDED, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
mUserSwitcherController, () -> {
|
||||
});
|
||||
mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
mUserSwitcherController, () -> {});
|
||||
ConstraintSet.Constraint viewFlipperConstraint =
|
||||
getViewConstraint(mSecurityViewFlipper.getId());
|
||||
assertThat(viewFlipperConstraint.layout.topToTop).isEqualTo(PARENT_ID);
|
||||
@@ -377,7 +378,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
private void setupUserSwitcher() {
|
||||
when(mGlobalSettings.getInt(any(), anyInt())).thenReturn(ONE_HANDED_KEYGUARD_SIDE_RIGHT);
|
||||
mKeyguardSecurityContainer.initMode(KeyguardSecurityContainer.MODE_USER_SWITCHER,
|
||||
mGlobalSettings, mFalsingManager, mUserSwitcherController);
|
||||
mGlobalSettings, mFalsingManager, mUserSwitcherController, () -> {});
|
||||
}
|
||||
|
||||
private ArrayList<UserRecord> buildUserRecords(int count) {
|
||||
@@ -387,7 +388,8 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
0 /* flags */);
|
||||
users.add(new UserRecord(info, null, false /* isGuest */, false /* isCurrent */,
|
||||
false /* isAddUser */, false /* isRestricted */, true /* isSwitchToEnabled */,
|
||||
false /* isAddSupervisedUser */, null /* enforcedAdmin */));
|
||||
false /* isAddSupervisedUser */, null /* enforcedAdmin */,
|
||||
false /* isManageUsers */));
|
||||
}
|
||||
return users;
|
||||
}
|
||||
@@ -395,7 +397,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
|
||||
private void setupForUpdateKeyguardPosition(boolean oneHandedMode) {
|
||||
int mode = oneHandedMode ? MODE_ONE_HANDED : MODE_DEFAULT;
|
||||
mKeyguardSecurityContainer.initMode(mode, mGlobalSettings, mFalsingManager,
|
||||
mUserSwitcherController);
|
||||
mUserSwitcherController, () -> {});
|
||||
}
|
||||
|
||||
/** Get the ConstraintLayout constraint of the view. */
|
||||
|
||||
@@ -57,14 +57,18 @@ import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shade.NotificationShadeWindowView
|
||||
import com.android.systemui.telephony.TelephonyListenerManager
|
||||
import com.android.systemui.user.data.source.UserRecord
|
||||
import com.android.systemui.user.legacyhelper.data.LegacyUserDataHelper
|
||||
import com.android.systemui.user.shared.model.UserActionModel
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
||||
import com.android.systemui.util.mockito.nullable
|
||||
import com.android.systemui.util.settings.GlobalSettings
|
||||
import com.android.systemui.util.settings.SecureSettings
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
@@ -123,7 +127,7 @@ class UserSwitcherControllerOldImplTest : SysuiTestCase() {
|
||||
private val ownerId = UserHandle.USER_SYSTEM
|
||||
private val ownerInfo = UserInfo(ownerId, "Owner", null,
|
||||
UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL or UserInfo.FLAG_INITIALIZED or
|
||||
UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM,
|
||||
UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM or UserInfo.FLAG_ADMIN,
|
||||
UserManager.USER_TYPE_FULL_SYSTEM)
|
||||
private val guestId = 1234
|
||||
private val guestInfo = UserInfo(guestId, "Guest", null,
|
||||
@@ -596,6 +600,76 @@ class UserSwitcherControllerOldImplTest : SysuiTestCase() {
|
||||
assertFalse(userSwitcherController.canCreateSupervisedUser())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanManageUser_userSwitcherEnabled_addUserWhenLocked() {
|
||||
`when`(
|
||||
globalSettings.getIntForUser(
|
||||
eq(Settings.Global.USER_SWITCHER_ENABLED),
|
||||
anyInt(),
|
||||
eq(UserHandle.USER_SYSTEM)
|
||||
)
|
||||
).thenReturn(1)
|
||||
|
||||
`when`(
|
||||
globalSettings.getIntForUser(
|
||||
eq(Settings.Global.ADD_USERS_WHEN_LOCKED),
|
||||
anyInt(),
|
||||
eq(UserHandle.USER_SYSTEM)
|
||||
)
|
||||
).thenReturn(1)
|
||||
setupController()
|
||||
assertTrue(userSwitcherController.canManageUsers())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanManageUser_userSwitcherDisabled_addUserWhenLocked() {
|
||||
`when`(
|
||||
globalSettings.getIntForUser(
|
||||
eq(Settings.Global.USER_SWITCHER_ENABLED),
|
||||
anyInt(),
|
||||
eq(UserHandle.USER_SYSTEM)
|
||||
)
|
||||
).thenReturn(0)
|
||||
|
||||
`when`(
|
||||
globalSettings.getIntForUser(
|
||||
eq(Settings.Global.ADD_USERS_WHEN_LOCKED),
|
||||
anyInt(),
|
||||
eq(UserHandle.USER_SYSTEM)
|
||||
)
|
||||
).thenReturn(1)
|
||||
setupController()
|
||||
assertFalse(userSwitcherController.canManageUsers())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanManageUser_userSwitcherEnabled_isAdmin() {
|
||||
`when`(
|
||||
globalSettings.getIntForUser(
|
||||
eq(Settings.Global.USER_SWITCHER_ENABLED),
|
||||
anyInt(),
|
||||
eq(UserHandle.USER_SYSTEM)
|
||||
)
|
||||
).thenReturn(1)
|
||||
|
||||
setupController()
|
||||
assertTrue(userSwitcherController.canManageUsers())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanManageUser_userSwitcherDisabled_isAdmin() {
|
||||
`when`(
|
||||
globalSettings.getIntForUser(
|
||||
eq(Settings.Global.USER_SWITCHER_ENABLED),
|
||||
anyInt(),
|
||||
eq(UserHandle.USER_SYSTEM)
|
||||
)
|
||||
).thenReturn(0)
|
||||
|
||||
setupController()
|
||||
assertFalse(userSwitcherController.canManageUsers())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addUserSwitchCallback() {
|
||||
val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>()
|
||||
@@ -632,4 +706,22 @@ class UserSwitcherControllerOldImplTest : SysuiTestCase() {
|
||||
bgExecutor.runAllReady()
|
||||
verify(userManager).createGuest(context)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onUserItemClicked_manageUsers() {
|
||||
val manageUserRecord = LegacyUserDataHelper.createRecord(
|
||||
mContext,
|
||||
ownerId,
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
isRestricted = false,
|
||||
isSwitchToEnabled = true
|
||||
)
|
||||
|
||||
userSwitcherController.onUserListItemClicked(manageUserRecord, null)
|
||||
val intentCaptor = kotlinArgumentCaptor<Intent>()
|
||||
verify(activityStarter).startActivity(intentCaptor.capture(),
|
||||
eq(true)
|
||||
)
|
||||
Truth.assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
fun `actions - device unlocked`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val userInfos = createUserInfos(count = 2, includeGuest = false)
|
||||
|
||||
userRepository.setUserInfos(userInfos)
|
||||
userRepository.setSelectedUserInfo(userInfos[0])
|
||||
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
|
||||
@@ -215,6 +216,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
UserActionModel.ENTER_GUEST_MODE,
|
||||
UserActionModel.ADD_USER,
|
||||
UserActionModel.ADD_SUPERVISED_USER,
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -276,6 +278,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
UserActionModel.ENTER_GUEST_MODE,
|
||||
UserActionModel.ADD_USER,
|
||||
UserActionModel.ADD_SUPERVISED_USER,
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -283,7 +286,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `actions - device locked - only guest action is shown`() =
|
||||
fun `actions - device locked - only guest action and manage user is shown`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val userInfos = createUserInfos(count = 2, includeGuest = false)
|
||||
userRepository.setUserInfos(userInfos)
|
||||
@@ -293,7 +296,13 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
var value: List<UserActionModel>? = null
|
||||
val job = underTest.actions.onEach { value = it }.launchIn(this)
|
||||
|
||||
assertThat(value).isEqualTo(listOf(UserActionModel.ENTER_GUEST_MODE))
|
||||
assertThat(value)
|
||||
.isEqualTo(
|
||||
listOf(
|
||||
UserActionModel.ENTER_GUEST_MODE,
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
|
||||
)
|
||||
)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
@@ -330,7 +339,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER)
|
||||
|
||||
val intentCaptor = kotlinArgumentCaptor<Intent>()
|
||||
verify(activityStarter).startActivity(intentCaptor.capture(), eq(false))
|
||||
verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
|
||||
assertThat(intentCaptor.value.action)
|
||||
.isEqualTo(UserManager.ACTION_CREATE_SUPERVISED_USER)
|
||||
assertThat(intentCaptor.value.`package`).isEqualTo(SUPERVISED_USER_CREATION_APP_PACKAGE)
|
||||
@@ -342,7 +351,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT)
|
||||
|
||||
val intentCaptor = kotlinArgumentCaptor<Intent>()
|
||||
verify(activityStarter).startActivity(intentCaptor.capture(), eq(false))
|
||||
verify(activityStarter).startActivity(intentCaptor.capture(), eq(true))
|
||||
assertThat(intentCaptor.value.action).isEqualTo(Settings.ACTION_USER_SETTINGS)
|
||||
}
|
||||
|
||||
@@ -561,6 +570,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
UserActionModel.ENTER_GUEST_MODE,
|
||||
UserActionModel.ADD_USER,
|
||||
UserActionModel.ADD_SUPERVISED_USER,
|
||||
UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -705,7 +715,7 @@ class UserInteractorRefactoredTest : UserInteractorTest() {
|
||||
name,
|
||||
/* iconPath= */ "",
|
||||
/* flags= */ if (isPrimary) {
|
||||
UserInfo.FLAG_PRIMARY
|
||||
UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN
|
||||
} else {
|
||||
0
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user