Add UI for multiple admins on Headless
In a series of CLs under topic add_ui_for_hsum_admins UI and functionality for allowing multiple admins on HSUM build is added. In User settings and User switcher when creating a new user there is a new dialog prompting to choose admin status of the user to be created. In User details view there is a toggle that is visible to admin users that allows to modify admin status of existing users. This toggle is only applicable to full users that are not supervised, guests or a main device user. Bug: 252790451 Test: croot && make RunSettingsRoboTests -j40 ROBOTEST_FILTER="com.android.settings.users.UserDetailsSettingsTest" Change-Id: I447dc168be30aa614aeb3f8b71ad14a7223fd7c1
This commit is contained in:
@@ -61,6 +61,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
private static final String KEY_SWITCH_USER = "switch_user";
|
||||
private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
|
||||
private static final String KEY_REMOVE_USER = "remove_user";
|
||||
private static final String KEY_GRANT_ADMIN = "user_grant_admin";
|
||||
private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
|
||||
private static final String KEY_APP_COPYING = "app_copying";
|
||||
|
||||
@@ -72,6 +73,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
private static final int DIALOG_SETUP_USER = 3;
|
||||
private static final int DIALOG_CONFIRM_RESET_GUEST = 4;
|
||||
private static final int DIALOG_CONFIRM_RESET_GUEST_AND_SWITCH_USER = 5;
|
||||
private static final int DIALOG_CONFIRM_REVOKE_ADMIN = 6;
|
||||
|
||||
/** Whether to enable the app_copying fragment. */
|
||||
private static final boolean SHOW_APP_COPYING_PREF = false;
|
||||
@@ -91,6 +93,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
Preference mAppCopyingPref;
|
||||
@VisibleForTesting
|
||||
Preference mRemoveUserPref;
|
||||
@VisibleForTesting
|
||||
SwitchPreference mGrantAdminPref;
|
||||
|
||||
@VisibleForTesting
|
||||
/** The user being studied (not the user doing the studying). */
|
||||
@@ -179,6 +183,12 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
mMetricsFeatureProvider.action(getActivity(),
|
||||
SettingsEnums.ACTION_DISABLE_USER_CALL);
|
||||
enableCallsAndSms(false);
|
||||
} else if (preference == mGrantAdminPref) {
|
||||
if (Boolean.FALSE.equals(newValue)) {
|
||||
showDialog(DIALOG_CONFIRM_REVOKE_ADMIN);
|
||||
return false;
|
||||
}
|
||||
updateUserAdminStatus(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -192,6 +202,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
return SettingsEnums.DIALOG_USER_REMOVE;
|
||||
case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
|
||||
return SettingsEnums.DIALOG_USER_ENABLE_CALLING_AND_SMS;
|
||||
case DIALOG_CONFIRM_REVOKE_ADMIN:
|
||||
return SettingsEnums.DIALOG_REVOKE_USER_ADMIN;
|
||||
case DIALOG_SETUP_USER:
|
||||
return SettingsEnums.DIALOG_USER_SETUP;
|
||||
default:
|
||||
@@ -235,6 +247,9 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
return UserDialogs.createRemoveGuestDialog(getActivity(),
|
||||
(dialog, which) -> switchUser());
|
||||
}
|
||||
case DIALOG_CONFIRM_REVOKE_ADMIN:
|
||||
return UserDialogs.createConfirmRevokeAdmin(getActivity(),
|
||||
(dialog, which) -> updateUserAdminStatus(false));
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
|
||||
}
|
||||
@@ -277,6 +292,9 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
mRemoveUserPref = findPreference(KEY_REMOVE_USER);
|
||||
mAppAndContentAccessPref = findPreference(KEY_APP_AND_CONTENT_ACCESS);
|
||||
mAppCopyingPref = findPreference(KEY_APP_COPYING);
|
||||
mGrantAdminPref = findPreference(KEY_GRANT_ADMIN);
|
||||
|
||||
mGrantAdminPref.setChecked(mUserInfo.isAdmin());
|
||||
|
||||
mSwitchUserPref.setTitle(
|
||||
context.getString(com.android.settingslib.R.string.user_switch_to_user,
|
||||
@@ -289,10 +307,15 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
mSwitchUserPref.setSelectable(true);
|
||||
mSwitchUserPref.setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
//TODO(b/261700461): remove preference for supervised user
|
||||
//TODO(b/262371063): check whether multiple admins allowed, not for HSUM
|
||||
if (mUserInfo.isMain() || mUserInfo.isGuest() || !UserManager.isHeadlessSystemUserMode()) {
|
||||
removePreference(KEY_GRANT_ADMIN);
|
||||
}
|
||||
if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
|
||||
removePreference(KEY_ENABLE_TELEPHONY);
|
||||
removePreference(KEY_REMOVE_USER);
|
||||
removePreference(KEY_GRANT_ADMIN);
|
||||
removePreference(KEY_APP_AND_CONTENT_ACCESS);
|
||||
removePreference(KEY_APP_COPYING);
|
||||
} else {
|
||||
@@ -339,6 +362,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
|
||||
mRemoveUserPref.setOnPreferenceClickListener(this);
|
||||
mPhonePref.setOnPreferenceChangeListener(this);
|
||||
mGrantAdminPref.setOnPreferenceChangeListener(this);
|
||||
mAppAndContentAccessPref.setOnPreferenceClickListener(this);
|
||||
mAppCopyingPref.setOnPreferenceClickListener(this);
|
||||
}
|
||||
@@ -401,6 +425,20 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets admin status of selected user. Method is called when toggle in
|
||||
* user details settings is switched.
|
||||
* @param isSetAdmin indicates if user admin status needs to be set to true.
|
||||
*/
|
||||
private void updateUserAdminStatus(boolean isSetAdmin) {
|
||||
mGrantAdminPref.setChecked(isSetAdmin);
|
||||
if (!isSetAdmin) {
|
||||
mUserManager.revokeUserAdmin(mUserInfo.id);
|
||||
} else if ((mUserInfo.flags & UserInfo.FLAG_ADMIN) == 0) {
|
||||
mUserManager.setUserAdmin(mUserInfo.id);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeUser() {
|
||||
mUserManager.removeUser(mUserInfo.id);
|
||||
finishFragment();
|
||||
|
@@ -202,4 +202,19 @@ public final class UserDialogs {
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dialog to confirm that the admin privileges of the user should be revoked.
|
||||
*
|
||||
* @param onConfirmListener Callback object for positive action
|
||||
*/
|
||||
public static Dialog createConfirmRevokeAdmin(Context context,
|
||||
DialogInterface.OnClickListener onConfirmListener) {
|
||||
return new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.user_revoke_admin_confirm_title)
|
||||
.setMessage(R.string.user_revoke_admin_confirm_message)
|
||||
.setPositiveButton(R.string.remove, onConfirmListener)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
@@ -84,6 +84,7 @@ import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import com.android.settingslib.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.users.EditUserInfoController;
|
||||
import com.android.settingslib.users.GrantAdminDialogController;
|
||||
import com.android.settingslib.users.UserCreatingDialog;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
@@ -156,6 +157,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
private static final int DIALOG_CONFIRM_RESET_AND_RESTART_GUEST = 13;
|
||||
private static final int DIALOG_CONFIRM_EXIT_GUEST_EPHEMERAL = 14;
|
||||
private static final int DIALOG_CONFIRM_EXIT_GUEST_NON_EPHEMERAL = 15;
|
||||
private static final int DIALOG_GRANT_ADMIN = 16;
|
||||
|
||||
private static final int MESSAGE_UPDATE_LIST = 1;
|
||||
private static final int MESSAGE_USER_CREATED = 2;
|
||||
@@ -215,6 +217,9 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
|
||||
|
||||
private MultiUserSwitchBarController mSwitchBarController;
|
||||
|
||||
private GrantAdminDialogController mGrantAdminDialogController =
|
||||
new GrantAdminDialogController();
|
||||
private EditUserInfoController mEditUserInfoController =
|
||||
new EditUserInfoController(Utils.FILE_PROVIDER_AUTHORITY);
|
||||
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
|
||||
@@ -228,6 +233,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
|
||||
private CharSequence mPendingUserName;
|
||||
private Drawable mPendingUserIcon;
|
||||
private boolean mGrantAdmin;
|
||||
|
||||
// A place to cache the generated default avatar
|
||||
private Drawable mDefaultIconDrawable;
|
||||
@@ -287,7 +293,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
mSwitchBarController = new MultiUserSwitchBarController(activity,
|
||||
new MainSwitchBarController(switchBar), this /* listener */);
|
||||
getSettingsLifecycle().addObserver(mSwitchBarController);
|
||||
|
||||
boolean openUserEditDialog = getIntent().getBooleanExtra(
|
||||
EXTRA_OPEN_DIALOG_USER_PROFILE_EDITOR, false);
|
||||
if (switchBar.isChecked() && openUserEditDialog) {
|
||||
@@ -306,7 +311,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
|
||||
mGuestUserAutoCreated = getPrefContext().getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_guestUserAutoCreated);
|
||||
com.android.internal.R.bool.config_guestUserAutoCreated);
|
||||
|
||||
mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
|
||||
activity, KEY_ADD_USER_WHEN_LOCKED);
|
||||
@@ -712,18 +717,27 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_USER);
|
||||
if (!longMessageDisplayed) {
|
||||
preferences.edit().putBoolean(
|
||||
KEY_ADD_USER_LONG_MESSAGE_DISPLAYED,
|
||||
true).apply();
|
||||
}
|
||||
//TODO(b/262371063): check whether multiple admins allowed,
|
||||
// not for HSUM
|
||||
if (UserManager.isHeadlessSystemUserMode()) {
|
||||
showDialog(DIALOG_GRANT_ADMIN);
|
||||
} else {
|
||||
showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_USER);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
return dlg;
|
||||
}
|
||||
case DIALOG_GRANT_ADMIN: {
|
||||
return buildGrantAdminDialog();
|
||||
}
|
||||
case DIALOG_CHOOSE_USER_TYPE: {
|
||||
List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
|
||||
HashMap<String, String> addUserItem = new HashMap<String, String>();
|
||||
@@ -931,6 +945,19 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
return d;
|
||||
}
|
||||
|
||||
private Dialog buildGrantAdminDialog() {
|
||||
return mGrantAdminDialogController.createDialog(
|
||||
getActivity(),
|
||||
(grantAdmin) -> {
|
||||
mGrantAdmin = grantAdmin;
|
||||
showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_USER);
|
||||
},
|
||||
() -> {
|
||||
mGrantAdmin = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDialogMetricsCategory(int dialogId) {
|
||||
switch (dialogId) {
|
||||
@@ -938,6 +965,8 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
return SettingsEnums.DIALOG_USER_REMOVE;
|
||||
case DIALOG_USER_CANNOT_MANAGE:
|
||||
return SettingsEnums.DIALOG_USER_CANNOT_MANAGE;
|
||||
case DIALOG_GRANT_ADMIN:
|
||||
return SettingsEnums.DIALOG_GRANT_USER_ADMIN;
|
||||
case DIALOG_ADD_USER:
|
||||
return SettingsEnums.DIALOG_USER_ADD;
|
||||
case DIALOG_CHOOSE_USER_TYPE:
|
||||
@@ -1031,6 +1060,9 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
userName,
|
||||
mUserManager.USER_TYPE_FULL_SECONDARY,
|
||||
0);
|
||||
if (mGrantAdmin) {
|
||||
mUserManager.setUserAdmin(user.id);
|
||||
}
|
||||
} else {
|
||||
user = mUserManager.createRestrictedProfile(userName);
|
||||
}
|
||||
@@ -1351,20 +1383,20 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
mGuestResetPreference.setVisible(true);
|
||||
|
||||
boolean isGuestFirstLogin = Settings.Secure.getIntForUser(
|
||||
getContext().getContentResolver(),
|
||||
SETTING_GUEST_HAS_LOGGED_IN,
|
||||
0,
|
||||
UserHandle.myUserId()) <= 1;
|
||||
getContext().getContentResolver(),
|
||||
SETTING_GUEST_HAS_LOGGED_IN,
|
||||
0,
|
||||
UserHandle.myUserId()) <= 1;
|
||||
String guestExitSummary;
|
||||
if (mUserCaps.mIsEphemeral) {
|
||||
guestExitSummary = getContext().getString(
|
||||
R.string.guest_notification_ephemeral);
|
||||
R.string.guest_notification_ephemeral);
|
||||
} else if (isGuestFirstLogin) {
|
||||
guestExitSummary = getContext().getString(
|
||||
R.string.guest_notification_non_ephemeral);
|
||||
R.string.guest_notification_non_ephemeral);
|
||||
} else {
|
||||
guestExitSummary = getContext().getString(
|
||||
R.string.guest_notification_non_ephemeral_non_first_login);
|
||||
R.string.guest_notification_non_ephemeral_non_first_login);
|
||||
}
|
||||
mGuestExitPreference.setSummary(guestExitSummary);
|
||||
}
|
||||
|
Reference in New Issue
Block a user