Snap for 7495277 from 477c5d9cde to sc-release

Change-Id: If1dbabede85fa7b5f771dd31d3d603fc45b40f3f
This commit is contained in:
Android Build Coastguard Worker
2021-06-26 03:08:23 +00:00
9 changed files with 214 additions and 26 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1211,7 +1211,7 @@
<!-- Text shown in fingerprint enroll when we didn't observe progress for a few seconds. [CHAR LIMIT=100] --> <!-- Text shown in fingerprint enroll when we didn't observe progress for a few seconds. [CHAR LIMIT=100] -->
<string name="security_settings_fingerprint_enroll_lift_touch_again">Lift finger, then touch sensor again</string> <string name="security_settings_fingerprint_enroll_lift_touch_again">Lift finger, then touch sensor again</string>
<!-- Text shown during fingerprint enrollment to indicate bad sensor calibration. [CHAR LIMIT=100] --> <!-- Text shown during fingerprint enrollment to indicate bad sensor calibration. [CHAR LIMIT=100] -->
<string name="security_settings_fingerprint_bad_calibration">Device repaired improperly. Fingerprint disabled.</string> <string name="security_settings_fingerprint_bad_calibration">Can\u2019t use fingerprint sensor. Visit a repair provider</string>
<!-- Text shown when "Add fingerprint" button is disabled --> <!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string> <string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
@@ -4393,6 +4393,25 @@
<!-- Header on first screen of choose work profile pattern flow [CHAR LIMIT=40] --> <!-- Header on first screen of choose work profile pattern flow [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_profile_pattern_header">Set a work pattern</string> <string name="lockpassword_choose_your_profile_pattern_header">Set a work pattern</string>
<!-- Header on first screen of choose device password flow [CHAR LIMIT=NONE] -->
<string name="lockpassword_choose_password_description" product="phone">For added security, set a password to unlock the phone</string>
<!-- Header on first screen of choose device PIN flow [CHAR LIMIT=NONE] -->
<string name="lockpassword_choose_pin_description" product="phone">For added security, set a PIN to unlock the phone</string>
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
<string name="lockpattern_choose_pattern_description" product="phone">For added security, set a pattern to unlock the phone</string>
<!-- Header on first screen of choose device password flow [CHAR LIMIT=NONE] -->
<string name="lockpassword_choose_password_description" product="tablet">For added security, set a password to unlock the tablet</string>
<!-- Header on first screen of choose device PIN flow [CHAR LIMIT=NONE] -->
<string name="lockpassword_choose_pin_description" product="tablet">For added security, set a PIN to unlock the tablet</string>
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
<string name="lockpattern_choose_pattern_description" product="tablet">For added security, set a pattern to unlock the tablet</string>
<!-- Header on first screen of choose device password flow [CHAR LIMIT=NONE] -->
<string name="lockpassword_choose_password_description" product="default">For added security, set a password to unlock the device</string>
<!-- Header on first screen of choose device PIN flow [CHAR LIMIT=NONE] -->
<string name="lockpassword_choose_pin_description" product="default">For added security, set a PIN to unlock the device</string>
<!-- Header on first screen of choose device pattern flow [CHAR LIMIT=NONE] -->
<string name="lockpattern_choose_pattern_description" product="default">For added security, set a pattern to unlock the device</string>
<!-- Header on first screen of choose password/PIN as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] --> <!-- Header on first screen of choose password/PIN as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_password_header_for_fingerprint">To use fingerprint, set password</string> <string name="lockpassword_choose_your_password_header_for_fingerprint">To use fingerprint, set password</string>
<!-- Header on first screen of choose pattern as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] --> <!-- Header on first screen of choose pattern as backup for fingerprint flow. If this string cannot be translated in under 40 characters, please translate "Set fingerprint backup" [CHAR LIMIT=40] -->
@@ -4438,12 +4457,12 @@
<!-- Header on first screen of choose password/PIN as backup for Face Unlock flow. If this string cannot be translated in under 40 characters, please translate "Set Face Unlock backup" [CHAR LIMIT=40] --> <!-- Header on first screen of choose password/PIN as backup for Face Unlock flow. If this string cannot be translated in under 40 characters, please translate "Set Face Unlock backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pin_header_for_face">To use Face Unlock, set PIN</string> <string name="lockpassword_choose_your_pin_header_for_face">To use Face Unlock, set PIN</string>
<!-- Header on first screen of choose password/PIN as backup for biometric unlock flow. If this string cannot be translated in under 40 characters, please translate "Set biometric unlock backup" [CHAR LIMIT=40] --> <!-- Title of a screen that asks the user to set up a password as a backup for Face or Fingerprint Unlock. If this string can't be translated in 60 characters, please translate "Set a backup password". [CHAR LIMIT=60] -->
<string name="lockpassword_choose_your_password_header_for_biometrics">To use biometrics, set password</string> <string name="lockpassword_choose_your_password_header_for_biometrics">Set a password to use face or fingerprint</string>
<!-- Header on first screen of choose pattern as backup for biometric unlock flow. If this string cannot be translated in under 40 characters, please translate "Set biometric unlock backup" [CHAR LIMIT=40] --> <!-- Title of a screen that asks the user to set up a pattern as a backup for Face or Fingerprint Unlock. If this string can't be translated in 60 characters, please translate "Set a backup pattern". [CHAR LIMIT=60] -->
<string name="lockpassword_choose_your_pattern_header_for_biometrics">To use biometrics, set pattern</string> <string name="lockpassword_choose_your_pattern_header_for_biometrics">Set a pattern to use face or fingerprint</string>
<!-- Header on first screen of choose password/PIN as backup for biometric unlock flow. If this string cannot be translated in under 40 characters, please translate "Set biometric unlock backup" [CHAR LIMIT=40] --> <!-- Title of a screen that asks the user to set up a PIN as a backup for Face or Fingerprint Unlock. If this string can't be translated in 60 characters, please translate "Set a backup PIN". [CHAR LIMIT=60] -->
<string name="lockpassword_choose_your_pin_header_for_biometrics">To use biometrics, set PIN</string> <string name="lockpassword_choose_your_pin_header_for_biometrics">Set a PIN to use face or fingerprint</string>
<!-- Text for button that the user should tap when they forgot their work profile password [CHAR LIMIT=40] --> <!-- Text for button that the user should tap when they forgot their work profile password [CHAR LIMIT=40] -->
@@ -10590,7 +10609,11 @@
<!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
select what the USB connection for this device should be used for. This choice select what the USB connection for this device should be used for. This choice
is for transcoding the files that are transferred via MTP. --> is for transcoding the files that are transferred via MTP. -->
<string name="usb_transcode_files">Transcode exported media</string> <string name="usb_transcode_files">Convert videos to AVC</string>
<!-- The summary text that appears when the user enables the 'Convert videos to AVC' option for
transcoding files to compatible formats before transferring them from the device to PC.
[CHAR LIMIT=NONE] -->
<string name="usb_transcode_files_summary">Videos will play on more media players, but quality may be reduced</string>
<!-- Description of one of the choices in a dialog (with title defined in usb_use) that lets the user <!-- Description of one of the choices in a dialog (with title defined in usb_use) that lets the user
select what the USB connection for this device should be used for. This choice select what the USB connection for this device should be used for. This choice
is for transferring photos via PTP. --> is for transferring photos via PTP. -->

View File

@@ -22,12 +22,9 @@
android:title="@string/smart_battery_manager_title" android:title="@string/smart_battery_manager_title"
settings:keywords="@string/keywords_battery_adaptive_preferences"> settings:keywords="@string/keywords_battery_adaptive_preferences">
<com.android.settings.widget.VideoPreference <com.android.settingslib.widget.IllustrationPreferencee
android:key="auto_awesome_battery" android:key="auto_awesome_battery"
android:title="@string/summary_placeholder" settings:lottie_rawRes="@raw/auto_awesome_battery_lottie" />
settings:animation="@raw/auto_awesome_battery"
settings:preview="@drawable/auto_awesome_battery"
settings:controller="com.android.settings.widget.VideoPreferenceController"/>
<SwitchPreference <SwitchPreference
android:key="smart_battery" android:key="smart_battery"

View File

@@ -50,13 +50,24 @@ public class ZenAccessController extends BasePreferenceController {
} }
public static Set<String> getPackagesRequestingNotificationPolicyAccess() { public static Set<String> getPackagesRequestingNotificationPolicyAccess() {
final String[] PERM = {
android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
};
return getPackagesWithPermissions(PERM);
}
public static Set<String> getPackagesWithManageNotifications() {
final String[] PERM = {
android.Manifest.permission.MANAGE_NOTIFICATIONS
};
return getPackagesWithPermissions(PERM);
}
public static Set<String> getPackagesWithPermissions(String[] permList) {
final ArraySet<String> requestingPackages = new ArraySet<>(); final ArraySet<String> requestingPackages = new ArraySet<>();
try { try {
final String[] PERM = {
android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
};
final ParceledListSlice list = AppGlobals.getPackageManager() final ParceledListSlice list = AppGlobals.getPackageManager()
.getPackagesHoldingPermissions(PERM, 0 /*flags*/, .getPackagesHoldingPermissions(permList, 0 /*flags*/,
ActivityManager.getCurrentUser()); ActivityManager.getCurrentUser());
final List<PackageInfo> pkgs = list.getList(); final List<PackageInfo> pkgs = list.getList();
if (pkgs != null) { if (pkgs != null) {

View File

@@ -55,6 +55,7 @@ public class UsbDetailsTranscodeMtpController extends UsbDetailsController
mSwitchPreference = new SwitchPreference(mPreferenceCategory.getContext()); mSwitchPreference = new SwitchPreference(mPreferenceCategory.getContext());
mSwitchPreference.setTitle(R.string.usb_transcode_files); mSwitchPreference.setTitle(R.string.usb_transcode_files);
mSwitchPreference.setOnPreferenceClickListener(this); mSwitchPreference.setOnPreferenceClickListener(this);
mSwitchPreference.setSummaryOn(R.string.usb_transcode_files_summary);
mPreferenceCategory.addPreference(mSwitchPreference); mPreferenceCategory.addPreference(mSwitchPreference);
} }

View File

@@ -17,6 +17,7 @@
package com.android.settings.notification.zen; package com.android.settings.notification.zen;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
@@ -117,6 +118,7 @@ public class ZenAccessSettings extends EmptyTextSettings implements
} }
ArraySet<String> autoApproved = new ArraySet<>(); ArraySet<String> autoApproved = new ArraySet<>();
autoApproved.addAll(mNoMan.getEnabledNotificationListenerPackages()); autoApproved.addAll(mNoMan.getEnabledNotificationListenerPackages());
autoApproved.addAll(ZenAccessController.getPackagesWithManageNotifications());
Collections.sort(apps, new PackageItemInfo.DisplayNameComparator(mPkgMan)); Collections.sort(apps, new PackageItemInfo.DisplayNameComparator(mPkgMan));
for (ApplicationInfo app : apps) { for (ApplicationInfo app : apps) {
final String pkg = app.packageName; final String pkg = app.packageName;

View File

@@ -42,6 +42,9 @@ import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import java.util.List; 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. * Settings screen for configuring, deleting or switching to a specific user.
@@ -67,9 +70,13 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
private static final int DIALOG_CONFIRM_ENABLE_CALLING = 2; 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_CONFIRM_ENABLE_CALLING_AND_SMS = 3;
private static final int DIALOG_SETUP_USER = 4; private static final int DIALOG_SETUP_USER = 4;
private static final int DIALOG_CONFIRM_RESET_GUEST = 5;
private UserManager mUserManager; private UserManager mUserManager;
private UserCapabilities mUserCaps; private UserCapabilities mUserCaps;
private boolean mGuestUserAutoCreated;
private final AtomicBoolean mGuestCreationScheduled = new AtomicBoolean();
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@VisibleForTesting @VisibleForTesting
RestrictedPreference mSwitchUserPref; RestrictedPreference mSwitchUserPref;
@@ -97,6 +104,9 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mUserCaps = UserCapabilities.create(context); mUserCaps = UserCapabilities.create(context);
addPreferencesFromResource(R.xml.user_details_settings); addPreferencesFromResource(R.xml.user_details_settings);
mGuestUserAutoCreated = getPrefContext().getResources().getBoolean(
com.android.internal.R.bool.config_guestUserAutoCreated);
initialize(context, getArguments()); initialize(context, getArguments());
} }
@@ -104,13 +114,20 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
mSwitchUserPref.setEnabled(canSwitchUserNow()); mSwitchUserPref.setEnabled(canSwitchUserNow());
if (mGuestUserAutoCreated) {
mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0);
}
} }
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
if (preference == mRemoveUserPref) { if (preference == mRemoveUserPref) {
if (canDeleteUser()) { if (canDeleteUser()) {
showDialog(DIALOG_CONFIRM_REMOVE); if (mUserInfo.isGuest()) {
showDialog(DIALOG_CONFIRM_RESET_GUEST);
} else {
showDialog(DIALOG_CONFIRM_REMOVE);
}
return true; return true;
} }
} else if (preference == mSwitchUserPref) { } else if (preference == mSwitchUserPref) {
@@ -144,6 +161,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
public int getDialogMetricsCategory(int dialogId) { public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) { switch (dialogId) {
case DIALOG_CONFIRM_REMOVE: case DIALOG_CONFIRM_REMOVE:
case DIALOG_CONFIRM_RESET_GUEST:
return SettingsEnums.DIALOG_USER_REMOVE; return SettingsEnums.DIALOG_USER_REMOVE;
case DIALOG_CONFIRM_ENABLE_CALLING: case DIALOG_CONFIRM_ENABLE_CALLING:
return SettingsEnums.DIALOG_USER_ENABLE_CALLING; return SettingsEnums.DIALOG_USER_ENABLE_CALLING;
@@ -179,10 +197,30 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
switchUser(); switchUser();
} }
}); });
case DIALOG_CONFIRM_RESET_GUEST:
return UserDialogs.createResetGuestDialog(getActivity(),
(dialog, which) -> resetGuest());
} }
throw new IllegalArgumentException("Unsupported dialogId " + dialogId); 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 @VisibleForTesting
@Override @Override
protected void showDialog(int dialogId) { protected void showDialog(int dialogId) {
@@ -239,11 +277,17 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
if (mUserInfo.isGuest()) { if (mUserInfo.isGuest()) {
// These are not for an existing user, just general Guest settings. // These are not for an existing user, just general Guest settings.
// Default title is for calling and SMS. Change to calling-only here // 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); mPhonePref.setTitle(R.string.user_enable_calling);
mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions(); mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
mPhonePref.setChecked( mPhonePref.setChecked(
!mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS)); !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 { } else {
mPhonePref.setChecked(!mUserManager.hasUserRestriction( mPhonePref.setChecked(!mUserManager.hasUserRestriction(
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId))); UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));

View File

@@ -154,4 +154,24 @@ public final class UserDialogs {
null) null)
.create(); .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();
}
} }

View File

@@ -87,6 +87,9 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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. * Screen that manages the list of users on the device.
@@ -128,6 +131,7 @@ public class UserSettings extends SettingsPreferenceFragment
private static final int DIALOG_USER_PROFILE_EDITOR = 9; 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_USER = 10;
private static final int DIALOG_USER_PROFILE_EDITOR_ADD_RESTRICTED_PROFILE = 11; 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_UPDATE_LIST = 1;
private static final int MESSAGE_USER_CREATED = 2; private static final int MESSAGE_USER_CREATED = 2;
@@ -136,6 +140,9 @@ public class UserSettings extends SettingsPreferenceFragment
private static final int USER_TYPE_RESTRICTED_PROFILE = 2; private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
private static final int REQUEST_CHOOSE_LOCK = 10; 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 = private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
"key_add_user_long_message_displayed"; "key_add_user_long_message_displayed";
@@ -160,6 +167,7 @@ public class UserSettings extends SettingsPreferenceFragment
SparseArray<Bitmap> mUserIcons = new SparseArray<>(); SparseArray<Bitmap> mUserIcons = new SparseArray<>();
private int mRemovingUserId = -1; private int mRemovingUserId = -1;
private boolean mAddingUser; private boolean mAddingUser;
private boolean mGuestUserAutoCreated;
private String mAddingUserName; private String mAddingUserName;
private UserCapabilities mUserCaps; private UserCapabilities mUserCaps;
private boolean mShouldUpdateUserList = true; private boolean mShouldUpdateUserList = true;
@@ -173,6 +181,8 @@ public class UserSettings extends SettingsPreferenceFragment
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController; private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController; private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController;
private UserCreatingDialog mUserCreatingDialog; private UserCreatingDialog mUserCreatingDialog;
private final AtomicBoolean mGuestCreationScheduled = new AtomicBoolean();
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private CharSequence mPendingUserName; private CharSequence mPendingUserName;
private Drawable mPendingUserIcon; private Drawable mPendingUserIcon;
@@ -240,6 +250,9 @@ public class UserSettings extends SettingsPreferenceFragment
return; return;
} }
mGuestUserAutoCreated = getPrefContext().getResources().getBoolean(
com.android.internal.R.bool.config_guestUserAutoCreated);
mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController( mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
activity, KEY_ADD_USER_WHEN_LOCKED); activity, KEY_ADD_USER_WHEN_LOCKED);
@@ -343,7 +356,10 @@ public class UserSettings extends SettingsPreferenceFragment
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
int pos = 0; 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(); String nickname = mUserManager.getUserName();
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++, MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
getResources().getString(R.string.user_remove_user_menu, nickname)); getResources().getString(R.string.user_remove_user_menu, nickname));
@@ -387,7 +403,9 @@ public class UserSettings extends SettingsPreferenceFragment
if (isCurrentUserGuest()) { if (isCurrentUserGuest()) {
// No need to load profile information // No need to load profile information
mMePreference.setIcon(getEncircledDefaultIcon()); 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); mMePreference.setSelectable(true);
// removing a guest will result in switching back to the admin user // removing a guest will result in switching back to the admin user
mMePreference.setEnabled(canSwitchUserNow()); mMePreference.setEnabled(canSwitchUserNow());
@@ -445,6 +463,9 @@ public class UserSettings extends SettingsPreferenceFragment
if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) { if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) {
addUserNow(USER_TYPE_RESTRICTED_PROFILE); addUserNow(USER_TYPE_RESTRICTED_PROFILE);
} }
} else if (mGuestUserAutoCreated && requestCode == REQUEST_EDIT_GUEST
&& resultCode == RESULT_GUEST_REMOVED) {
scheduleGuestCreation();
} else { } else {
mEditUserInfoController.onActivityResult(requestCode, resultCode, data); mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
} }
@@ -508,12 +529,15 @@ public class UserSettings extends SettingsPreferenceFragment
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser); extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
final Context context = getContext(); final Context context = getContext();
new SubSettingLauncher(context) SubSettingLauncher launcher = new SubSettingLauncher(context)
.setDestination(UserDetailsSettings.class.getName()) .setDestination(UserDetailsSettings.class.getName())
.setArguments(extras) .setArguments(extras)
.setTitleText(getUserName(context, userInfo)) .setTitleText(getUserName(context, userInfo))
.setSourceMetricsCategory(getMetricsCategory()) .setSourceMetricsCategory(getMetricsCategory());
.launch(); if (mGuestUserAutoCreated && userInfo.isGuest()) {
launcher.setResultListener(this, REQUEST_EDIT_GUEST);
}
launcher.launch();
} }
@Override @Override
@@ -651,6 +675,10 @@ public class UserSettings extends SettingsPreferenceFragment
} }
return buildAddUserDialog(USER_TYPE_RESTRICTED_PROFILE); return buildAddUserDialog(USER_TYPE_RESTRICTED_PROFILE);
} }
case DIALOG_CONFIRM_RESET_GUEST: {
return UserDialogs.createResetGuestDialog(getActivity(),
(dialog, which) -> resetGuest());
}
default: default:
return null; return null;
} }
@@ -727,6 +755,7 @@ public class UserSettings extends SettingsPreferenceFragment
case DIALOG_NEED_LOCKSCREEN: case DIALOG_NEED_LOCKSCREEN:
return SettingsEnums.DIALOG_USER_NEED_LOCKSCREEN; return SettingsEnums.DIALOG_USER_NEED_LOCKSCREEN;
case DIALOG_CONFIRM_EXIT_GUEST: case DIALOG_CONFIRM_EXIT_GUEST:
case DIALOG_CONFIRM_RESET_GUEST:
return SettingsEnums.DIALOG_USER_CONFIRM_EXIT_GUEST; return SettingsEnums.DIALOG_USER_CONFIRM_EXIT_GUEST;
case DIALOG_USER_PROFILE_EDITOR: case DIALOG_USER_PROFILE_EDITOR:
case DIALOG_USER_PROFILE_EDITOR_ADD_USER: case DIALOG_USER_PROFILE_EDITOR_ADD_USER:
@@ -840,6 +869,55 @@ public class UserSettings extends SettingsPreferenceFragment
removeThisUser(); 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 @VisibleForTesting
void updateUserList() { void updateUserList() {
final Context context = getActivity(); final Context context = getActivity();
@@ -988,8 +1066,15 @@ public class UserSettings extends SettingsPreferenceFragment
&& mUserCaps.mUserSwitcherEnabled) { && mUserCaps.mUserSwitcherEnabled) {
mAddGuest.setVisible(true); mAddGuest.setVisible(true);
mAddGuest.setIcon(getEncircledDefaultIcon()); mAddGuest.setIcon(getEncircledDefaultIcon());
mAddGuest.setEnabled(canSwitchUserNow());
mAddGuest.setSelectable(true); 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 { } else {
mAddGuest.setVisible(false); mAddGuest.setVisible(false);
} }
@@ -1077,7 +1162,11 @@ public class UserSettings extends SettingsPreferenceFragment
public boolean onPreferenceClick(Preference pref) { public boolean onPreferenceClick(Preference pref) {
if (pref == mMePreference) { if (pref == mMePreference) {
if (isCurrentUserGuest()) { if (isCurrentUserGuest()) {
showDialog(DIALOG_CONFIRM_EXIT_GUEST); if (mGuestUserAutoCreated) {
showDialog(DIALOG_CONFIRM_RESET_GUEST);
} else {
showDialog(DIALOG_CONFIRM_EXIT_GUEST);
}
} else { } else {
showDialog(DIALOG_USER_PROFILE_EDITOR); showDialog(DIALOG_USER_PROFILE_EDITOR);
} }