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

Commit b04ad237 authored by András Klöczl's avatar András Klöczl Committed by Automerger Merge Worker
Browse files

Merge "Change user setup prompt dialog showing logic" into rvc-dev am: f8754b4d am: 974efbd7

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/11686951

Change-Id: I437174b4527d3cc15527b62b409cfa9a5b9d35ac
parents c0681db2 974efbd7
Loading
Loading
Loading
Loading
+43 −5
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedPreference;

import java.util.List;

@@ -65,10 +66,13 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
    private static final int DIALOG_CONFIRM_REMOVE = 1;
    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 UserManager mUserManager;
    private UserCapabilities mUserCaps;

    @VisibleForTesting
    Preference mSwitchUserPref;
    RestrictedPreference mSwitchUserPref;
    private SwitchPreference mPhonePref;
    @VisibleForTesting
    Preference mAppAndContentAccessPref;
@@ -90,6 +94,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment

        final Context context = getActivity();
        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        mUserCaps = UserCapabilities.create(context);
        addPreferencesFromResource(R.xml.user_details_settings);

        initialize(context, getArguments());
@@ -106,15 +111,20 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
        if (preference == mRemoveUserPref) {
            if (canDeleteUser()) {
                showDialog(DIALOG_CONFIRM_REMOVE);
            }
                return true;
            }
        } else if (preference == mSwitchUserPref) {
            if (canSwitchUserNow()) {
                if (shouldShowSetupPromptDialog()) {
                    showDialog(DIALOG_SETUP_USER);
                } else {
                    switchUser();
                }
                return true;
            }
        } else if (preference == mAppAndContentAccessPref) {
            openAppAndContentAccessScreen(false);
            return true;
        }
        return false;
    }
@@ -139,6 +149,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
                return SettingsEnums.DIALOG_USER_ENABLE_CALLING;
            case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
                return SettingsEnums.DIALOG_USER_ENABLE_CALLING_AND_SMS;
            case DIALOG_SETUP_USER:
                return SettingsEnums.DIALOG_USER_SETUP;
            default:
                return 0;
        }
@@ -160,6 +172,13 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
            case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
                return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(),
                        (dialog, which) -> enableCallsAndSms(true));
            case DIALOG_SETUP_USER:
                return UserDialogs.createSetupUserDialog(getActivity(),
                        (dialog, which) -> {
                            if (canSwitchUserNow()) {
                                switchUser();
                            }
                        });
        }
        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
    }
@@ -188,7 +207,14 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
        mSwitchUserPref.setTitle(
                context.getString(com.android.settingslib.R.string.user_switch_to_user,
                        mUserInfo.name));

        if (mUserCaps.mDisallowSwitchUser) {
            mSwitchUserPref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context));
        } else {
            mSwitchUserPref.setDisabledByAdmin(null);
            mSwitchUserPref.setSelectable(true);
            mSwitchUserPref.setOnPreferenceClickListener(this);
        }

        if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
            removePreference(KEY_ENABLE_TELEPHONY);
@@ -321,4 +347,16 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
                .setSourceMetricsCategory(getMetricsCategory())
                .launch();
    }

    private boolean isSecondaryUser(UserInfo user) {
        return UserManager.USER_TYPE_FULL_SECONDARY.equals(user.userType);
    }

    private boolean shouldShowSetupPromptDialog() {
        // TODO: FLAG_INITIALIZED is set when a user is switched to for the first time,
        //  but what we would really need here is a flag that shows if the setup process was
        //  completed. After the user cancels the setup process, mUserInfo.isInitialized() will
        //  return true so there will be no setup prompt dialog shown to the user anymore.
        return isSecondaryUser(mUserInfo) && !mUserInfo.isInitialized();
    }
}
+17 −0
Original line number Diff line number Diff line
@@ -138,4 +138,21 @@ public final class UserDialogs {
                .setNegativeButton(android.R.string.cancel, null)
                .create();
    }

    /**
     * Creates a dialog to confirm that the user is ok to start setting up a new user.
     *
     * @param onConfirmListener Callback object for positive action
     */
    public static Dialog createSetupUserDialog(Context context,
            DialogInterface.OnClickListener onConfirmListener) {
        return new AlertDialog.Builder(context)
                .setTitle(com.android.settingslib.R.string.user_setup_dialog_title)
                .setMessage(com.android.settingslib.R.string.user_setup_dialog_message)
                .setPositiveButton(com.android.settingslib.R.string.user_setup_button_setup_now,
                        onConfirmListener)
                .setNegativeButton(com.android.settingslib.R.string.user_setup_button_setup_later,
                        null)
                .create();
    }
}
+28 −116
Original line number Diff line number Diff line
@@ -102,8 +102,6 @@ public class UserSettings extends SettingsPreferenceFragment

    /** UserId of the user being removed */
    private static final String SAVE_REMOVING_USER = "removing_user";
    /** UserId of the user that was just added */
    private static final String SAVE_ADDING_USER = "adding_user";

    private static final String KEY_USER_LIST = "user_list";
    private static final String KEY_USER_ME = "user_me";
@@ -119,8 +117,7 @@ public class UserSettings extends SettingsPreferenceFragment

    private static final int DIALOG_CONFIRM_REMOVE = 1;
    private static final int DIALOG_ADD_USER = 2;
    private static final int DIALOG_SETUP_USER = 3;
    private static final int DIALOG_SETUP_PROFILE = 4;
    // Dialogs with id 3 and 4 got removed
    private static final int DIALOG_USER_CANNOT_MANAGE = 5;
    private static final int DIALOG_CHOOSE_USER_TYPE = 6;
    private static final int DIALOG_NEED_LOCKSCREEN = 7;
@@ -130,8 +127,7 @@ public class UserSettings extends SettingsPreferenceFragment
    private static final int DIALOG_USER_PROFILE_EDITOR_ADD_RESTRICTED_PROFILE = 11;

    private static final int MESSAGE_UPDATE_LIST = 1;
    private static final int MESSAGE_SETUP_USER = 2;
    private static final int MESSAGE_CONFIG_USER = 3;
    private static final int MESSAGE_USER_CREATED = 2;

    private static final int USER_TYPE_USER = 1;
    private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
@@ -160,7 +156,6 @@ public class UserSettings extends SettingsPreferenceFragment
    @VisibleForTesting
    SparseArray<Bitmap> mUserIcons = new SparseArray<>();
    private int mRemovingUserId = -1;
    private int mAddedUserId = 0;
    private boolean mAddingUser;
    private String mAddingUserName;
    private UserCapabilities mUserCaps;
@@ -187,12 +182,9 @@ public class UserSettings extends SettingsPreferenceFragment
                case MESSAGE_UPDATE_LIST:
                    updateUserList();
                    break;
                case MESSAGE_SETUP_USER:
                case MESSAGE_USER_CREATED:
                    onUserCreated(msg.arg1);
                    break;
                case MESSAGE_CONFIG_USER:
                    onManageUserClicked(msg.arg1, true);
                    break;
            }
        }
    };
@@ -254,9 +246,6 @@ public class UserSettings extends SettingsPreferenceFragment
                .setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController);

        if (icicle != null) {
            if (icicle.containsKey(SAVE_ADDING_USER)) {
                mAddedUserId = icicle.getInt(SAVE_ADDING_USER);
            }
            if (icicle.containsKey(SAVE_REMOVING_USER)) {
                mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
            }
@@ -334,7 +323,6 @@ public class UserSettings extends SettingsPreferenceFragment
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mEditUserInfoController.onSaveInstanceState(outState);
        outState.putInt(SAVE_ADDING_USER, mAddedUserId);
        outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
    }

@@ -482,15 +470,15 @@ public class UserSettings extends SettingsPreferenceFragment
        }
    }

    private void onManageUserClicked(int userId, boolean newUser) {
    private void onUserCreated(int userId) {
        mAddingUser = false;
        UserInfo userInfo = mUserManager.getUserInfo(userId);
        if (userId == UserHandle.myUserId()) {
            // Jump to owner info panel
            OwnerInfoSettings.show(this);
        } else {
        openUserDetails(userInfo, true);
    }

    private void openUserDetails(UserInfo userInfo, boolean newUser) {
        Bundle extras = new Bundle();
            extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
        extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userInfo.id);
        extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
        new SubSettingLauncher(getContext())
                .setDestination(UserDetailsSettings.class.getName())
@@ -499,21 +487,6 @@ public class UserSettings extends SettingsPreferenceFragment
                .setSourceMetricsCategory(getMetricsCategory())
                .launch();
    }
    }

    private void onUserCreated(int userId) {
        mAddedUserId = userId;
        mAddingUser = false;
        if (!isResumed()) {
            Log.w(TAG, "Cannot show dialog after onPause");
            return;
        }
        if (mUserManager.getUserInfo(userId).isRestricted()) {
            showDialog(DIALOG_SETUP_PROFILE);
        } else {
            showDialog(DIALOG_SETUP_USER);
        }
    }

    @Override
    public void onDialogShowing() {
@@ -571,37 +544,6 @@ public class UserSettings extends SettingsPreferenceFragment
                        .create();
                return dlg;
            }
            case DIALOG_SETUP_USER: {
                Dialog dlg = new AlertDialog.Builder(context)
                        .setTitle(com.android.settingslib.R.string.user_setup_dialog_title)
                        .setMessage(com.android.settingslib.R.string.user_setup_dialog_message)
                        .setPositiveButton(
                                com.android.settingslib.R.string.user_setup_button_setup_now,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {
                                        switchUserNow(mAddedUserId);
                                    }
                                })
                        .setNegativeButton(
                                com.android.settingslib.R.string.user_setup_button_setup_later,
                                null)
                        .create();
                return dlg;
            }
            case DIALOG_SETUP_PROFILE: {
                Dialog dlg = new AlertDialog.Builder(context)
                        .setMessage(
                                com.android.settingslib.R.string.user_setup_profile_dialog_message)
                        .setPositiveButton(android.R.string.ok,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {
                                        switchUserNow(mAddedUserId);
                                    }
                                })
                        .setNegativeButton(android.R.string.cancel, null)
                        .create();
                return dlg;
            }
            case DIALOG_CHOOSE_USER_TYPE: {
                List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
                HashMap<String, String> addUserItem = new HashMap<String, String>();
@@ -764,10 +706,6 @@ public class UserSettings extends SettingsPreferenceFragment
                return SettingsEnums.DIALOG_USER_CANNOT_MANAGE;
            case DIALOG_ADD_USER:
                return SettingsEnums.DIALOG_USER_ADD;
            case DIALOG_SETUP_USER:
                return SettingsEnums.DIALOG_USER_SETUP;
            case DIALOG_SETUP_PROFILE:
                return SettingsEnums.DIALOG_USER_SETUP_PROFILE;
            case DIALOG_CHOOSE_USER_TYPE:
                return SettingsEnums.DIALOG_USER_CHOOSE_TYPE;
            case DIALOG_NEED_LOCKSCREEN:
@@ -853,16 +791,11 @@ public class UserSettings extends SettingsPreferenceFragment

                    if (userType == USER_TYPE_USER) {
                        mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
                        // Skip setting up user which results in user switching when the
                        // restriction is set.
                        if (!mUserCaps.mDisallowSwitchUser) {
                            mHandler.sendMessage(mHandler.obtainMessage(
                                    MESSAGE_SETUP_USER, user.id, user.serialNumber));
                    }
                    } else {

                    mHandler.sendMessage(mHandler.obtainMessage(
                                MESSAGE_CONFIG_USER, user.id, user.serialNumber));
                    }
                            MESSAGE_USER_CREATED, user.id, user.serialNumber));

                    mPendingUserIcon = null;
                    mPendingUserName = null;
                }
@@ -870,18 +803,6 @@ public class UserSettings extends SettingsPreferenceFragment
        });
    }

    private void switchUserNow(int userId) {
        if (!canSwitchUserNow()) {
            return;
        }

        try {
            ActivityManager.getService().switchUser(userId);
        } catch (RemoteException re) {
            Log.e(TAG, "Error while switching to other user.");
        }
    }

    /**
     * Erase the current user (guest) and switch to another user.
     */
@@ -1125,21 +1046,14 @@ public class UserSettings extends SettingsPreferenceFragment
        if (pref == mMePreference) {
            if (isCurrentUserGuest()) {
                showDialog(DIALOG_CONFIRM_EXIT_GUEST);
                return true;
            }
            showDialog(DIALOG_USER_PROFILE_EDITOR);
        } else if (pref instanceof UserPreference) {
            int userId = ((UserPreference) pref).getUserId();
            // Get the latest status of the user
            UserInfo user = mUserManager.getUserInfo(userId);
            if (!user.isInitialized() && isSecondaryUser(user)) {
                // for uninitialized secondary users we should show a prompt dialog before
                // starting the setup
                mHandler.sendMessage(mHandler.obtainMessage(
                        MESSAGE_SETUP_USER, user.id, user.serialNumber));
            } else {
                onManageUserClicked(userId, false);
                showDialog(DIALOG_USER_PROFILE_EDITOR);
            }
            return true;
        } else if (pref instanceof UserPreference) {
            UserInfo userInfo = mUserManager.getUserInfo(((UserPreference) pref).getUserId());
            openUserDetails(userInfo, false);
            return true;
        } else if (pref == mAddUser) {
            // If we allow both types, show a picker, otherwise directly go to
            // flow for full user.
@@ -1148,10 +1062,12 @@ public class UserSettings extends SettingsPreferenceFragment
            } else {
                onAddUserClicked(USER_TYPE_USER);
            }
            return true;
        } else if (pref == mAddGuest) {
            UserInfo guest = mUserManager.createGuest(
                    getContext(), getString(com.android.settingslib.R.string.user_guest));
            switchUserNow(guest.id);
            openUserDetails(guest, true);
            return true;
        }
        return false;
    }
@@ -1265,8 +1181,4 @@ public class UserSettings extends SettingsPreferenceFragment
                    return niks;
                }
            };

    private boolean isSecondaryUser(UserInfo user) {
        return UserManager.USER_TYPE_FULL_SECONDARY.equals(user.userType);
    }
}
+35 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.robolectric.Shadows.shadowOf;

import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -53,6 +54,8 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;

import org.junit.After;
import org.junit.Before;
@@ -91,7 +94,7 @@ public class UserDetailsSettingsTest {
    private ShadowUserManager mUserManager;

    @Mock
    private Preference mSwitchUserPref;
    private RestrictedPreference mSwitchUserPref;
    @Mock
    private SwitchPreference mPhonePref;
    @Mock
@@ -101,6 +104,7 @@ public class UserDetailsSettingsTest {

    private FragmentActivity mActivity;
    private Context mContext;
    private UserCapabilities mUserCapabilities;
    private UserDetailsSettings mFragment;
    private Bundle mArguments;
    private UserInfo mUserInfo;
@@ -111,6 +115,8 @@ public class UserDetailsSettingsTest {

        mActivity = spy(ActivityController.of(new FragmentActivity()).get());
        mContext = spy(RuntimeEnvironment.application);
        mUserCapabilities = UserCapabilities.create(mContext);
        mUserCapabilities.mUserSwitcherEnabled = true;
        mFragment = spy(new UserDetailsSettings());
        mArguments = new Bundle();

@@ -121,6 +127,7 @@ public class UserDetailsSettingsTest {
        doReturn(mTelephonyManager).when(mActivity).getSystemService(Context.TELEPHONY_SERVICE);

        ReflectionHelpers.setField(mFragment, "mUserManager", userManager);
        ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
        doReturn(mActivity).when(mFragment).getActivity();
        doReturn(mActivity).when(mFragment).getContext();

@@ -426,6 +433,33 @@ public class UserDetailsSettingsTest {
        verify(mPhonePref).setChecked(false);
    }

    @Test
    public void initialize_switchUserDisallowed_shouldSetAdminDisabledOnSwitchPreference() {
        setupSelectedUser();
        mUserCapabilities.mDisallowSwitchUser = true;
        DevicePolicyManager devicePolicyManager = mock(DevicePolicyManager.class);
        doReturn(devicePolicyManager).when(mActivity)
                .getSystemService(Context.DEVICE_POLICY_SERVICE);
        doReturn(mock(ComponentName.class)).when(devicePolicyManager)
                .getDeviceOwnerComponentOnAnyUser();

        mFragment.initialize(mActivity, mArguments);

        verify(mSwitchUserPref).setDisabledByAdmin(any(RestrictedLockUtils.EnforcedAdmin.class));
    }

    @Test
    public void initialize_switchUserAllowed_shouldSetSwitchPreferenceEnabled() {
        setupSelectedUser();
        mUserCapabilities.mDisallowSwitchUser = false;

        mFragment.initialize(mActivity, mArguments);

        verify(mSwitchUserPref).setDisabledByAdmin(null);
        verify(mSwitchUserPref).setSelectable(true);
        verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
    }

    @Test
    public void onPreferenceClick_switchClicked_canSwitch_shouldSwitch() {
        setupSelectedUser();
+30 −0
Original line number Diff line number Diff line
@@ -33,13 +33,16 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -53,6 +56,8 @@ import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;

import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedLockUtils;
@@ -70,6 +75,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowIntent;
import org.robolectric.util.ReflectionHelpers;

import java.util.Arrays;
@@ -589,6 +595,30 @@ public class UserSettingsTest {
        verify(mUserManager, times(2)).getUsers(true);
    }

    @Test
    public void onPreferenceClick_addGuestClicked_createGuestAndOpenDetails() {
        UserInfo createdGuest = getGuest(false);
        removeFlag(createdGuest, UserInfo.FLAG_INITIALIZED);
        doReturn(createdGuest).when(mUserManager).createGuest(mActivity, "Guest");
        doReturn(mActivity).when(mFragment).getContext();

        mFragment.onPreferenceClick(mAddGuestPreference);

        verify(mUserManager).createGuest(mActivity, "Guest");
        Intent startedIntent = shadowOf(mActivity).getNextStartedActivity();
        ShadowIntent shadowIntent = shadowOf(startedIntent);
        assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class);
        assertThat(startedIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
                .isEqualTo(UserDetailsSettings.class.getName());
        Bundle arguments = startedIntent.getBundleExtra(
                SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
        assertThat(arguments).isNotNull();
        assertThat(arguments.getInt(UserDetailsSettings.EXTRA_USER_ID, 0))
                .isEqualTo(createdGuest.id);
        assertThat(arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false))
                .isEqualTo(true);
    }

    @Test
    public void getRealUsersCount_onlyAdmin_shouldCount() {
        givenUsers(getAdminUser(true));