Merge "Change user setup prompt dialog showing logic" into rvc-dev
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index c7cf90d..897b3c7 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -39,6 +39,7 @@
 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 @@
     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 @@
 
         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 @@
         if (preference == mRemoveUserPref) {
             if (canDeleteUser()) {
                 showDialog(DIALOG_CONFIRM_REMOVE);
+                return true;
             }
-            return true;
         } else if (preference == mSwitchUserPref) {
             if (canSwitchUserNow()) {
-                switchUser();
+                if (shouldShowSetupPromptDialog()) {
+                    showDialog(DIALOG_SETUP_USER);
+                } else {
+                    switchUser();
+                }
+                return true;
             }
-            return true;
         } else if (preference == mAppAndContentAccessPref) {
             openAppAndContentAccessScreen(false);
+            return true;
         }
         return false;
     }
@@ -139,6 +149,8 @@
                 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 @@
             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 @@
         mSwitchUserPref.setTitle(
                 context.getString(com.android.settingslib.R.string.user_switch_to_user,
                         mUserInfo.name));
-        mSwitchUserPref.setOnPreferenceClickListener(this);
+
+        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 @@
                 .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();
+    }
 }
diff --git a/src/com/android/settings/users/UserDialogs.java b/src/com/android/settings/users/UserDialogs.java
index 2361e44..0fb9636 100644
--- a/src/com/android/settings/users/UserDialogs.java
+++ b/src/com/android/settings/users/UserDialogs.java
@@ -138,4 +138,21 @@
                 .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();
+    }
 }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 719ed4a..910917a 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -102,8 +102,6 @@
 
     /** 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 @@
 
     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 @@
     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 @@
     @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 @@
                 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 @@
                 .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 void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         mEditUserInfoController.onSaveInstanceState(outState);
-        outState.putInt(SAVE_ADDING_USER, mAddedUserId);
         outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
     }
 
@@ -482,37 +470,22 @@
         }
     }
 
-    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 {
-            Bundle extras = new Bundle();
-            extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
-            extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
-            new SubSettingLauncher(getContext())
-                    .setDestination(UserDetailsSettings.class.getName())
-                    .setArguments(extras)
-                    .setTitleText(userInfo.name)
-                    .setSourceMetricsCategory(getMetricsCategory())
-                    .launch();
-        }
+        openUserDetails(userInfo, true);
     }
 
-    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);
-        }
+    private void openUserDetails(UserInfo userInfo, boolean newUser) {
+        Bundle extras = new Bundle();
+        extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userInfo.id);
+        extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
+        new SubSettingLauncher(getContext())
+                .setDestination(UserDetailsSettings.class.getName())
+                .setArguments(extras)
+                .setTitleText(userInfo.name)
+                .setSourceMetricsCategory(getMetricsCategory())
+                .launch();
     }
 
     @Override
@@ -571,37 +544,6 @@
                         .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 @@
                 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 @@
 
                     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));
                     }
+
+                    mHandler.sendMessage(mHandler.obtainMessage(
+                            MESSAGE_USER_CREATED, user.id, user.serialNumber));
+
                     mPendingUserIcon = null;
                     mPendingUserName = null;
                 }
@@ -870,18 +803,6 @@
         });
     }
 
-    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 @@
         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 @@
             } 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 @@
                     return niks;
                 }
             };
-
-    private boolean isSecondaryUser(UserInfo user) {
-        return UserManager.USER_TYPE_FULL_SECONDARY.equals(user.userType);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
index 56e4957..90c9172 100644
--- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
@@ -34,6 +34,7 @@
 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.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 @@
     private ShadowUserManager mUserManager;
 
     @Mock
-    private Preference mSwitchUserPref;
+    private RestrictedPreference mSwitchUserPref;
     @Mock
     private SwitchPreference mPhonePref;
     @Mock
@@ -101,6 +104,7 @@
 
     private FragmentActivity mActivity;
     private Context mContext;
+    private UserCapabilities mUserCapabilities;
     private UserDetailsSettings mFragment;
     private Bundle mArguments;
     private UserInfo mUserInfo;
@@ -111,6 +115,8 @@
 
         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 @@
         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();
 
@@ -427,6 +434,33 @@
     }
 
     @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();
         mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
index 3104c3c..2057788 100644
--- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
@@ -33,13 +33,16 @@
 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.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.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;
@@ -590,6 +596,30 @@
     }
 
     @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));