Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f11fdb3e authored by Rajeev Kumar's avatar Rajeev Kumar Committed by Android (Google) Code Review
Browse files

Merge "Make use of config for auto-created guest users" into sc-dev

parents f9aa12f4 8d37a2bb
Loading
Loading
Loading
Loading
+46 −2
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ import com.android.settingslib.RestrictedLockUtilsInternal;
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 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
    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 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
        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 class UserDetailsSettings extends SettingsPreferenceFragment
    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()) {
                if (mUserInfo.isGuest()) {
                    showDialog(DIALOG_CONFIRM_RESET_GUEST);
                } else {
                    showDialog(DIALOG_CONFIRM_REMOVE);
                }
                return true;
            }
        } else if (preference == mSwitchUserPref) {
@@ -144,6 +161,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
    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 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
                                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 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
            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)));
+20 −0
Original line number Diff line number Diff line
@@ -154,4 +154,24 @@ public final class UserDialogs {
                        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();
    }
}
+96 −7
Original line number Diff line number Diff line
@@ -87,6 +87,9 @@ import java.util.ArrayList;
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 @@ public class UserSettings extends SettingsPreferenceFragment
    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 @@ public class UserSettings extends SettingsPreferenceFragment
    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 @@ public class UserSettings extends SettingsPreferenceFragment
    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 @@ public class UserSettings extends SettingsPreferenceFragment
    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 @@ public class UserSettings extends SettingsPreferenceFragment
            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 @@ public class UserSettings extends SettingsPreferenceFragment
    @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 @@ public class UserSettings extends SettingsPreferenceFragment
        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 @@ public class UserSettings extends SettingsPreferenceFragment
            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 @@ public class UserSettings extends SettingsPreferenceFragment
        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 @@ public class UserSettings extends SettingsPreferenceFragment
                }
                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 @@ public class UserSettings extends SettingsPreferenceFragment
            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 @@ public class UserSettings extends SettingsPreferenceFragment
        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 @@ public class UserSettings extends SettingsPreferenceFragment
                && 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 class UserSettings extends SettingsPreferenceFragment
    public boolean onPreferenceClick(Preference pref) {
        if (pref == mMePreference) {
            if (isCurrentUserGuest()) {
                if (mGuestUserAutoCreated) {
                    showDialog(DIALOG_CONFIRM_RESET_GUEST);
                } else {
                    showDialog(DIALOG_CONFIRM_EXIT_GUEST);
                }
            } else {
                showDialog(DIALOG_USER_PROFILE_EDITOR);
            }