Merge "Make use of config for auto-created guest users" into sc-dev am: f11fdb3e50
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/14988090
Change-Id: Ic7fe5344e6a75d60eab7767b2f89cadc7ec1d2b2
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index ac6a8ea..ce186f2 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -42,6 +42,9 @@
import com.android.settingslib.RestrictedPreference;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Settings screen for configuring, deleting or switching to a specific user.
@@ -67,9 +70,13 @@
private static final int DIALOG_CONFIRM_ENABLE_CALLING = 2;
private static final int DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS = 3;
private static final int DIALOG_SETUP_USER = 4;
+ private static final int DIALOG_CONFIRM_RESET_GUEST = 5;
private UserManager mUserManager;
private UserCapabilities mUserCaps;
+ private boolean mGuestUserAutoCreated;
+ private final AtomicBoolean mGuestCreationScheduled = new AtomicBoolean();
+ private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@VisibleForTesting
RestrictedPreference mSwitchUserPref;
@@ -97,6 +104,9 @@
mUserCaps = UserCapabilities.create(context);
addPreferencesFromResource(R.xml.user_details_settings);
+ mGuestUserAutoCreated = getPrefContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated);
+
initialize(context, getArguments());
}
@@ -104,13 +114,20 @@
public void onResume() {
super.onResume();
mSwitchUserPref.setEnabled(canSwitchUserNow());
+ if (mGuestUserAutoCreated) {
+ mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0);
+ }
}
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference == mRemoveUserPref) {
if (canDeleteUser()) {
- showDialog(DIALOG_CONFIRM_REMOVE);
+ if (mUserInfo.isGuest()) {
+ showDialog(DIALOG_CONFIRM_RESET_GUEST);
+ } else {
+ showDialog(DIALOG_CONFIRM_REMOVE);
+ }
return true;
}
} else if (preference == mSwitchUserPref) {
@@ -144,6 +161,7 @@
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
case DIALOG_CONFIRM_REMOVE:
+ case DIALOG_CONFIRM_RESET_GUEST:
return SettingsEnums.DIALOG_USER_REMOVE;
case DIALOG_CONFIRM_ENABLE_CALLING:
return SettingsEnums.DIALOG_USER_ENABLE_CALLING;
@@ -179,10 +197,30 @@
switchUser();
}
});
+ case DIALOG_CONFIRM_RESET_GUEST:
+ return UserDialogs.createResetGuestDialog(getActivity(),
+ (dialog, which) -> resetGuest());
}
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
}
+ /**
+ * Erase the current guest user and create a new one in the background. UserSettings will
+ * handle guest creation after receiving the {@link UserSettings.RESULT_GUEST_REMOVED} result.
+ */
+ private void resetGuest() {
+ // Just to be safe, check that the selected user is a guest
+ if (!mUserInfo.isGuest()) {
+ return;
+ }
+ mMetricsFeatureProvider.action(getActivity(),
+ SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED);
+
+ mUserManager.removeUser(mUserInfo.id);
+ setResult(UserSettings.RESULT_GUEST_REMOVED);
+ finishFragment();
+ }
+
@VisibleForTesting
@Override
protected void showDialog(int dialogId) {
@@ -239,11 +277,17 @@
if (mUserInfo.isGuest()) {
// These are not for an existing user, just general Guest settings.
// Default title is for calling and SMS. Change to calling-only here
+ // TODO(b/191483069): These settings can't be changed unless guest user exists
mPhonePref.setTitle(R.string.user_enable_calling);
mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
mPhonePref.setChecked(
!mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
- mRemoveUserPref.setTitle(R.string.user_exit_guest_title);
+ mRemoveUserPref.setTitle(mGuestUserAutoCreated
+ ? com.android.settingslib.R.string.guest_reset_guest
+ : R.string.user_exit_guest_title);
+ if (mGuestUserAutoCreated) {
+ mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0);
+ }
} else {
mPhonePref.setChecked(!mUserManager.hasUserRestriction(
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
diff --git a/src/com/android/settings/users/UserDialogs.java b/src/com/android/settings/users/UserDialogs.java
index 9aab5b0..6915e95 100644
--- a/src/com/android/settings/users/UserDialogs.java
+++ b/src/com/android/settings/users/UserDialogs.java
@@ -154,4 +154,24 @@
null)
.create();
}
+
+ /**
+ * Creates a dialog to confirm with the user if it's ok to reset the guest user, which will
+ * delete all the guest user's data.
+ *
+ * @param context a Context object
+ * @param onConfirmListener Callback object for positive action
+ * @return the created Dialog
+ */
+ public static Dialog createResetGuestDialog(Context context,
+ DialogInterface.OnClickListener onConfirmListener) {
+ return new AlertDialog.Builder(context)
+ .setTitle(com.android.settingslib.R.string.guest_reset_guest_dialog_title)
+ .setMessage(R.string.user_exit_guest_confirm_message)
+ .setPositiveButton(
+ com.android.settingslib.R.string.guest_reset_guest_confirm_button,
+ onConfirmListener)
+ .setNegativeButton(android.R.string.cancel, null)
+ .create();
+ }
}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index e95fed7..ee23fc3 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -87,6 +87,9 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Screen that manages the list of users on the device.
@@ -128,6 +131,7 @@
private static final int DIALOG_USER_PROFILE_EDITOR = 9;
private static final int DIALOG_USER_PROFILE_EDITOR_ADD_USER = 10;
private static final int DIALOG_USER_PROFILE_EDITOR_ADD_RESTRICTED_PROFILE = 11;
+ private static final int DIALOG_CONFIRM_RESET_GUEST = 12;
private static final int MESSAGE_UPDATE_LIST = 1;
private static final int MESSAGE_USER_CREATED = 2;
@@ -136,6 +140,9 @@
private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
private static final int REQUEST_CHOOSE_LOCK = 10;
+ private static final int REQUEST_EDIT_GUEST = 11;
+
+ static final int RESULT_GUEST_REMOVED = 100;
private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
"key_add_user_long_message_displayed";
@@ -160,6 +167,7 @@
SparseArray<Bitmap> mUserIcons = new SparseArray<>();
private int mRemovingUserId = -1;
private boolean mAddingUser;
+ private boolean mGuestUserAutoCreated;
private String mAddingUserName;
private UserCapabilities mUserCaps;
private boolean mShouldUpdateUserList = true;
@@ -173,6 +181,8 @@
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController;
private UserCreatingDialog mUserCreatingDialog;
+ private final AtomicBoolean mGuestCreationScheduled = new AtomicBoolean();
+ private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private CharSequence mPendingUserName;
private Drawable mPendingUserIcon;
@@ -240,6 +250,9 @@
return;
}
+ mGuestUserAutoCreated = getPrefContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated);
+
mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
activity, KEY_ADD_USER_WHEN_LOCKED);
@@ -343,7 +356,10 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
int pos = 0;
- if (!mUserCaps.mIsAdmin && canSwitchUserNow()) {
+ // TODO(b/191509236): The menu item does not need to be accessible for guest users,
+ // regardless of mGuestUserAutoCreated
+ if (!mUserCaps.mIsAdmin && canSwitchUserNow() && !(isCurrentUserGuest()
+ && mGuestUserAutoCreated)) {
String nickname = mUserManager.getUserName();
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
getResources().getString(R.string.user_remove_user_menu, nickname));
@@ -387,7 +403,9 @@
if (isCurrentUserGuest()) {
// No need to load profile information
mMePreference.setIcon(getEncircledDefaultIcon());
- mMePreference.setTitle(R.string.user_exit_guest_title);
+ mMePreference.setTitle(
+ mGuestUserAutoCreated ? com.android.settingslib.R.string.guest_reset_guest
+ : R.string.user_exit_guest_title);
mMePreference.setSelectable(true);
// removing a guest will result in switching back to the admin user
mMePreference.setEnabled(canSwitchUserNow());
@@ -445,6 +463,9 @@
if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) {
addUserNow(USER_TYPE_RESTRICTED_PROFILE);
}
+ } else if (mGuestUserAutoCreated && requestCode == REQUEST_EDIT_GUEST
+ && resultCode == RESULT_GUEST_REMOVED) {
+ scheduleGuestCreation();
} else {
mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
}
@@ -508,12 +529,15 @@
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
final Context context = getContext();
- new SubSettingLauncher(context)
+ SubSettingLauncher launcher = new SubSettingLauncher(context)
.setDestination(UserDetailsSettings.class.getName())
.setArguments(extras)
.setTitleText(getUserName(context, userInfo))
- .setSourceMetricsCategory(getMetricsCategory())
- .launch();
+ .setSourceMetricsCategory(getMetricsCategory());
+ if (mGuestUserAutoCreated && userInfo.isGuest()) {
+ launcher.setResultListener(this, REQUEST_EDIT_GUEST);
+ }
+ launcher.launch();
}
@Override
@@ -651,6 +675,10 @@
}
return buildAddUserDialog(USER_TYPE_RESTRICTED_PROFILE);
}
+ case DIALOG_CONFIRM_RESET_GUEST: {
+ return UserDialogs.createResetGuestDialog(getActivity(),
+ (dialog, which) -> resetGuest());
+ }
default:
return null;
}
@@ -727,6 +755,7 @@
case DIALOG_NEED_LOCKSCREEN:
return SettingsEnums.DIALOG_USER_NEED_LOCKSCREEN;
case DIALOG_CONFIRM_EXIT_GUEST:
+ case DIALOG_CONFIRM_RESET_GUEST:
return SettingsEnums.DIALOG_USER_CONFIRM_EXIT_GUEST;
case DIALOG_USER_PROFILE_EDITOR:
case DIALOG_USER_PROFILE_EDITOR_ADD_USER:
@@ -840,6 +869,55 @@
removeThisUser();
}
+ /**
+ * Erase the current user (assuming it is a guest user), and create a new one in the background
+ */
+ @VisibleForTesting
+ void resetGuest() {
+ // Just to be safe
+ if (!isCurrentUserGuest()) {
+ return;
+ }
+ int guestUserId = UserHandle.myUserId();
+ // Using markGuestForDeletion allows us to create a new guest before this one is
+ // fully removed. This could happen if someone calls scheduleGuestCreation()
+ // immediately after calling this method.
+ boolean marked = mUserManager.markGuestForDeletion(guestUserId);
+ if (!marked) {
+ Log.w(TAG, "Couldn't mark the guest for deletion for user " + guestUserId);
+ return;
+ }
+ exitGuest();
+ scheduleGuestCreation();
+ }
+
+ /**
+ * Create a guest user in the background
+ */
+ @VisibleForTesting
+ void scheduleGuestCreation() {
+ // TODO(b/191067027): Move guest recreation to system_server
+ if (mGuestCreationScheduled.compareAndSet(/* expect= */ false, /* update= */ true)) {
+ // Once mGuestCreationScheduled=true, mAddGuest needs to be updated so that it shows
+ // "Resetting guest..."
+ mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
+ mExecutor.execute(() -> {
+ UserInfo guest = mUserManager.createGuest(
+ getContext(), getString(com.android.settingslib.R.string.user_guest));
+ mGuestCreationScheduled.set(false);
+ if (guest == null) {
+ Log.e(TAG, "Unable to automatically recreate guest user");
+ }
+ // The list needs to be updated whether or not guest creation worked. If guest
+ // creation failed, the list needs to update so that "Add guest" is displayed.
+ // Otherwise, the UX could be stuck in a state where there is no way to switch to
+ // the guest user (e.g. Guest would not be selectable, and it would be stuck
+ // saying "Resetting guest...")
+ mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
+ });
+ }
+ }
+
@VisibleForTesting
void updateUserList() {
final Context context = getActivity();
@@ -988,8 +1066,15 @@
&& mUserCaps.mUserSwitcherEnabled) {
mAddGuest.setVisible(true);
mAddGuest.setIcon(getEncircledDefaultIcon());
- mAddGuest.setEnabled(canSwitchUserNow());
mAddGuest.setSelectable(true);
+ if (mGuestUserAutoCreated && mGuestCreationScheduled.get()) {
+ mAddGuest.setTitle(com.android.settingslib.R.string.user_guest);
+ mAddGuest.setSummary(R.string.guest_resetting);
+ mAddGuest.setEnabled(false);
+ } else {
+ mAddGuest.setTitle(com.android.settingslib.R.string.guest_new_guest);
+ mAddGuest.setEnabled(canSwitchUserNow());
+ }
} else {
mAddGuest.setVisible(false);
}
@@ -1077,7 +1162,11 @@
public boolean onPreferenceClick(Preference pref) {
if (pref == mMePreference) {
if (isCurrentUserGuest()) {
- showDialog(DIALOG_CONFIRM_EXIT_GUEST);
+ if (mGuestUserAutoCreated) {
+ showDialog(DIALOG_CONFIRM_RESET_GUEST);
+ } else {
+ showDialog(DIALOG_CONFIRM_EXIT_GUEST);
+ }
} else {
showDialog(DIALOG_USER_PROFILE_EDITOR);
}