Merge "Add RESTRICTED bucket to Developer Options."
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 396a485..9c3a622 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -957,6 +957,9 @@
         <item>IPSec Xauth PSK</item>
         <item>IPSec Xauth RSA</item>
         <item>IPSec Hybrid RSA</item>
+        <item>IKEv2/IPSec MSCHAPv2</item>
+        <item>IKEv2/IPSec PSK</item>
+        <item>IKEv2/IPSec RSA</item>
     </string-array>
 
     <!-- Match this with the constants in VpnProfile. --> <skip />
@@ -968,6 +971,9 @@
         <item>IPSec VPN with pre-shared keys and Xauth authentication</item>
         <item>IPSec VPN with certificates and Xauth authentication</item>
         <item>IPSec VPN with certificates and hybrid authentication</item>
+        <item>IKEv2/IPSec VPN with certificates and username/password authentication</item>
+        <item>IKEv2/IPSec VPN with pre-shared keys</item>
+        <item>IKEv2/IPSec VPN with certificates</item>
     </string-array>
 
     <!-- VPN proxy settings. -->
diff --git a/res/values/config.xml b/res/values/config.xml
index fc2ca1f..86be2cb 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -434,4 +434,7 @@
 
     <!-- Package name of dialer supports RTT setting-->
     <string name="config_rtt_setting_package_name" translatable="false"></string>
+
+    <!--Whether tether settings should be shown in one screen or not-->
+    <bool name="config_show_all_in_one_tether_settings">false</bool>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index eede918..a153249 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11510,7 +11510,7 @@
     <!-- DSU Loader. Do not translate. -->
     <string name="dsu_loader_title" translatable="false">DSU Loader</string>
     <!-- DSU Loader Description. Do not translate. -->
-    <string name="dsu_loader_description" translatable="false">Load a Dyanmic System Update Image</string>
+    <string name="dsu_loader_description" translatable="false">Load a Dynamic System Update Image</string>
     <!-- DSU Loader Loading. Do not translate. -->
     <string name="dsu_loader_loading" translatable="false">Loading...</string>
 
diff --git a/src/com/android/settings/AllInOneTetherSettings.java b/src/com/android/settings/AllInOneTetherSettings.java
index fbf0280..1c7ea1d 100644
--- a/src/com/android/settings/AllInOneTetherSettings.java
+++ b/src/com/android/settings/AllInOneTetherSettings.java
@@ -201,7 +201,7 @@
         // Assume we are in a SettingsActivity. This is only safe because we currently use
         // SettingsActivity as base for all preference fragments.
         final SettingsActivity activity = (SettingsActivity) getActivity();
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
                     BluetoothProfile.PAN);
@@ -405,6 +405,12 @@
                 }
 
                 @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return context.getResources().getBoolean(
+                            R.bool.config_show_all_in_one_tether_settings);
+                }
+
+                @Override
                 public List<AbstractPreferenceController> createPreferenceControllers(
                         Context context) {
                     return buildPreferenceControllers(context, null /* AllTetherSettings */);
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index 97b5a0f..2dbfd62 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -545,7 +545,7 @@
         params.format = PixelFormat.TRANSLUCENT;
         params.windowAnimations = com.android.internal.R.style.Animation_Toast;
         params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
-        params.setFitWindowInsetsTypes(params.getFitWindowInsetsTypes() & ~Type.statusBars());
+        params.setFitInsetsTypes(params.getFitInsetsTypes() & ~Type.statusBars());
         params.setTitle(errorMessage);
         params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index c5407c5..da86cbf 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -451,6 +451,12 @@
                 }
 
                 @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return !context.getResources().getBoolean(
+                            R.bool.config_show_all_in_one_tether_settings);
+                }
+
+                @Override
                 public List<String> getNonIndexableKeys(Context context) {
                     final List<String> keys = super.getNonIndexableKeys(context);
                     final ConnectivityManager cm =
diff --git a/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java b/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
index 48a6aec..3f0defd 100644
--- a/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
+++ b/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
@@ -54,7 +54,9 @@
 
         mController = use(RecentLocationRequestSeeAllPreferenceController.class);
         mController.init(this);
-        mController.setProfileType(profileType);
+        if (profileType != 0) {
+            mController.setProfileType(profileType);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 326d44b..091e7f5 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -137,6 +137,10 @@
     String[] mReadOnlyApnTypes;
     @VisibleForTesting
     String[] mDefaultApnTypes;
+    @VisibleForTesting
+    String mDefaultApnProtocol;
+    @VisibleForTesting
+    String mDefaultApnRoamingProtocol;
     private String[] mReadOnlyApnFields;
     private boolean mReadOnlyApn;
     private Uri mCarrierUri;
@@ -241,12 +245,14 @@
     private static final int AUTH_TYPE_INDEX = 14;
     @VisibleForTesting
     static final int TYPE_INDEX = 15;
-    private static final int PROTOCOL_INDEX = 16;
+    @VisibleForTesting
+    static final int PROTOCOL_INDEX = 16;
     @VisibleForTesting
     static final int CARRIER_ENABLED_INDEX = 17;
     private static final int BEARER_INDEX = 18;
     private static final int BEARER_BITMASK_INDEX = 19;
-    private static final int ROAMING_PROTOCOL_INDEX = 20;
+    @VisibleForTesting
+    static final int ROAMING_PROTOCOL_INDEX = 20;
     private static final int MVNO_TYPE_INDEX = 21;
     private static final int MVNO_MATCH_DATA_INDEX = 22;
     private static final int EDITED_INDEX = 23;
@@ -317,6 +323,19 @@
                 if (!ArrayUtils.isEmpty(mDefaultApnTypes)) {
                     Log.d(TAG, "onCreate: default apn types: " + Arrays.toString(mDefaultApnTypes));
                 }
+
+                mDefaultApnProtocol = b.getString(
+                        CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_PROTOCOL_STRING);
+                if (!TextUtils.isEmpty(mDefaultApnProtocol)) {
+                    Log.d(TAG, "onCreate: default apn protocol: " + mDefaultApnProtocol);
+                }
+
+                mDefaultApnRoamingProtocol = b.getString(
+                        CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING);
+                if (!TextUtils.isEmpty(mDefaultApnRoamingProtocol)) {
+                    Log.d(TAG, "onCreate: default apn roaming protocol: "
+                            + mDefaultApnRoamingProtocol);
+                }
             }
         }
 
@@ -1029,13 +1048,13 @@
 
         callUpdate = setStringValueAndCheckIfDiff(values,
                 Telephony.Carriers.PROTOCOL,
-                checkNotSet(mProtocol.getValue()),
+                getUserEnteredApnProtocol(mProtocol, mDefaultApnProtocol),
                 callUpdate,
                 PROTOCOL_INDEX);
 
         callUpdate = setStringValueAndCheckIfDiff(values,
                 Telephony.Carriers.ROAMING_PROTOCOL,
-                checkNotSet(mRoamingProtocol.getValue()),
+                getUserEnteredApnProtocol(mRoamingProtocol, mDefaultApnRoamingProtocol),
                 callUpdate,
                 ROAMING_PROTOCOL_INDEX);
 
@@ -1232,6 +1251,17 @@
     }
 
     @VisibleForTesting
+    String getUserEnteredApnProtocol(ListPreference preference, String defaultApnProtocol) {
+        // if user has not specified a protocol or enter empty type, map it just for default
+        final String userEnteredApnProtocol = checkNotSet(
+                ((preference == null) ? null : preference.getValue()));
+        if (TextUtils.isEmpty(userEnteredApnProtocol)) {
+            return defaultApnProtocol;
+        }
+        return userEnteredApnProtocol.trim();
+    }
+
+    @VisibleForTesting
     String getUserEnteredApnType() {
         // if user has not specified a type, map it to "ALL APN TYPES THAT ARE NOT READ-ONLY"
         // but if user enter empty type, map it just for default
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index 0d4a6a6..5e52692 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -109,6 +109,10 @@
 
             // Grey out if provisioning is not available.
             mPreference.setEnabled(!TetherSettings.isProvisioningNeededButUnavailable(mContext));
+
+            if (mContext.getResources().getBoolean(R.bool.config_show_all_in_one_tether_settings)) {
+                mPreference.setFragment("com.android.settings.AllInOneTetherSettings");
+            }
         }
     }
 
diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
index 2340236..ab8327c 100644
--- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
@@ -200,7 +200,7 @@
 
     private Color[] getColors() {
         final Resources res = getContext().getResources();
-        final int[] colorInts = res.getIntArray(com.android.internal.R.array.sim_colors);
+        final int[] colorInts = res.getIntArray(android.R.array.simColors);
         final String[] colorStrings = res.getStringArray(R.array.color_picker);
         final int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size);
         final int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width);
diff --git a/src/com/android/settings/users/EditUserInfoController.java b/src/com/android/settings/users/EditUserInfoController.java
index 4d9244a..373d6a9 100644
--- a/src/com/android/settings/users/EditUserInfoController.java
+++ b/src/com/android/settings/users/EditUserInfoController.java
@@ -20,10 +20,8 @@
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -39,7 +37,6 @@
 import androidx.fragment.app.Fragment;
 
 import com.android.settings.R;
-import com.android.settingslib.Utils;
 import com.android.settingslib.drawable.CircleFramedDrawable;
 
 import java.io.File;
@@ -59,9 +56,24 @@
     private UserManager mUserManager;
     private boolean mWaitingForActivityResult = false;
 
+    /**
+     * Callback made when either the username text or photo choice changes.
+     */
     public interface OnContentChangedCallback {
-        public void onPhotoChanged(Drawable photo);
-        public void onLabelChanged(CharSequence label);
+        /** Photo updated. */
+        void onPhotoChanged(UserHandle user, Drawable photo);
+        /** Username updated. */
+        void onLabelChanged(UserHandle user, CharSequence label);
+    }
+
+    /**
+     * Callback made when the dialog finishes.
+     */
+    public interface OnDialogCompleteCallback {
+        /** Dialog closed with positive button. */
+        void onPositive();
+        /** Dialog closed with negative button or cancelled. */
+        void onNegativeOrCancel();
     }
 
     public void clear() {
@@ -111,7 +123,8 @@
 
     public Dialog createDialog(final Fragment fragment, final Drawable currentUserIcon,
             final CharSequence currentUserName,
-            int titleResId, final OnContentChangedCallback callback, UserHandle user) {
+            String title, final OnContentChangedCallback callback, UserHandle user,
+            OnDialogCompleteCallback completeCallback) {
         Activity activity = fragment.getActivity();
         mUser = user;
         if (mUserManager == null) {
@@ -120,10 +133,8 @@
         LayoutInflater inflater = activity.getLayoutInflater();
         View content = inflater.inflate(R.layout.edit_user_info_dialog_content, null);
 
-        UserInfo info = mUserManager.getUserInfo(mUser.getIdentifier());
-
         final EditText userNameView = (EditText) content.findViewById(R.id.user_name);
-        userNameView.setText(info.name);
+        userNameView.setText(currentUserName);
 
         final ImageView userPhotoView = (ImageView) content.findViewById(R.id.user_photo);
         Drawable drawable = null;
@@ -131,14 +142,11 @@
             drawable = CircleFramedDrawable.getInstance(activity, mSavedPhoto);
         } else {
             drawable = currentUserIcon;
-            if (drawable == null) {
-                drawable = Utils.getUserIcon(activity, mUserManager, info);
-            }
         }
         userPhotoView.setImageDrawable(drawable);
         mEditUserPhotoController = createEditUserPhotoController(fragment, userPhotoView, drawable);
         mEditUserInfoDialog = new AlertDialog.Builder(activity)
-                .setTitle(R.string.profile_info_settings_title)
+                .setTitle(title)
                 .setView(content)
                 .setCancelable(true)
                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@@ -149,41 +157,45 @@
                             CharSequence userName = userNameView.getText();
                             if (!TextUtils.isEmpty(userName)) {
                                 if (currentUserName == null
-                                        || !userName.toString().equals(currentUserName.toString())) {
+                                        || !userName.toString().equals(
+                                                currentUserName.toString())) {
                                     if (callback != null) {
-                                        callback.onLabelChanged(userName.toString());
+                                        callback.onLabelChanged(mUser, userName.toString());
                                     }
-                                    mUserManager.setUserName(mUser.getIdentifier(),
-                                            userName.toString());
                                 }
                             }
                             // Update the photo if changed.
                             Drawable drawable = mEditUserPhotoController.getNewUserPhotoDrawable();
-                            Bitmap bitmap = mEditUserPhotoController.getNewUserPhotoBitmap();
-                            if (drawable != null && bitmap != null
-                                    && !drawable.equals(currentUserIcon)) {
+                            if (drawable != null && !drawable.equals(currentUserIcon)) {
                                 if (callback != null) {
-                                    callback.onPhotoChanged(drawable);
+                                        callback.onPhotoChanged(mUser, drawable);
                                 }
-                                new AsyncTask<Void, Void, Void>() {
-                                    @Override
-                                    protected Void doInBackground(Void... params) {
-                                        mUserManager.setUserIcon(mUser.getIdentifier(),
-                                                mEditUserPhotoController.getNewUserPhotoBitmap());
-                                        return null;
-                                    }
-                                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
                             }
                             fragment.getActivity().removeDialog(
                                     RestrictedProfileSettings.DIALOG_ID_EDIT_USER_INFO);
                         }
                         clear();
+                        if (completeCallback != null) {
+                            completeCallback.onPositive();
+                        }
                     }
                 })
                 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         clear();
+                        if (completeCallback != null) {
+                            completeCallback.onNegativeOrCancel();
+                        }
+                    }
+                })
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        clear();
+                        if (completeCallback != null) {
+                            completeCallback.onNegativeOrCancel();
+                        }
                     }
                 })
                 .create();
diff --git a/src/com/android/settings/users/RestrictedProfileSettings.java b/src/com/android/settings/users/RestrictedProfileSettings.java
index b00ee83..57c0d02 100644
--- a/src/com/android/settings/users/RestrictedProfileSettings.java
+++ b/src/com/android/settings/users/RestrictedProfileSettings.java
@@ -23,12 +23,15 @@
 import android.content.pm.UserInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.util.UserIcons;
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settingslib.utils.ThreadUtils;
 
 public class RestrictedProfileSettings extends AppRestrictionsFragment
         implements EditUserInfoController.OnContentChangedCallback {
@@ -117,8 +120,8 @@
     public Dialog onCreateDialog(int dialogId) {
         if (dialogId == DIALOG_ID_EDIT_USER_INFO) {
             return mEditUserInfoController.createDialog(this, mUserIconView.getDrawable(),
-                    mUserNameView.getText(), R.string.profile_info_settings_title,
-                    this, mUser);
+                    mUserNameView.getText(), getString(R.string.profile_info_settings_title),
+                    this, mUser, null);
         } else if (dialogId == DIALOG_CONFIRM_REMOVE) {
             Dialog dlg =
                     UserDialogs.createRemoveDialog(getActivity(), mUser.getIdentifier(),
@@ -156,12 +159,19 @@
     }
 
     @Override
-    public void onPhotoChanged(Drawable photo) {
+    public void onPhotoChanged(UserHandle user, Drawable photo) {
         mUserIconView.setImageDrawable(photo);
+        ThreadUtils.postOnBackgroundThread(new Runnable() {
+            @Override
+            public void run() {
+                mUserManager.setUserIcon(user.getIdentifier(), UserIcons.convertToBitmap(photo));
+            }
+        });
     }
 
     @Override
-    public void onLabelChanged(CharSequence label) {
+    public void onLabelChanged(UserHandle user, CharSequence label) {
         mUserNameView.setText(label);
+        mUserManager.setUserName(user.getIdentifier(), label.toString());
     }
 }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 7a9f026..cd305e9 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.users;
 
+import static android.os.Process.myUserHandle;
+
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.Dialog;
@@ -73,6 +75,7 @@
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.drawable.CircleFramedDrawable;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.utils.ThreadUtils;
 
 import com.google.android.setupcompat.util.WizardManagerHelper;
 
@@ -82,6 +85,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Random;
 
 /**
  * Screen that manages the list of users on the device.
@@ -95,8 +99,7 @@
 public class UserSettings extends SettingsPreferenceFragment
         implements Preference.OnPreferenceClickListener, View.OnClickListener,
         MultiUserSwitchBarController.OnMultiUserSwitchChangedListener,
-        DialogInterface.OnDismissListener,
-        EditUserInfoController.OnContentChangedCallback {
+        DialogInterface.OnDismissListener {
 
     private static final String TAG = "UserSettings";
 
@@ -125,6 +128,8 @@
     private static final int DIALOG_NEED_LOCKSCREEN = 7;
     private static final int DIALOG_CONFIRM_EXIT_GUEST = 8;
     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 MESSAGE_UPDATE_LIST = 1;
     private static final int MESSAGE_SETUP_USER = 2;
@@ -168,6 +173,9 @@
     private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
     private MultiUserFooterPreferenceController mMultiUserFooterPreferenceController;
 
+    private CharSequence mPendingUserName;
+    private Drawable mPendingUserIcon;
+
     // A place to cache the generated default avatar
     private Drawable mDefaultIconDrawable;
 
@@ -447,7 +455,7 @@
                         break;
                     case USER_TYPE_RESTRICTED_PROFILE:
                         if (hasLockscreenSecurity()) {
-                            addUserNow(USER_TYPE_RESTRICTED_PROFILE);
+                            showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_RESTRICTED_PROFILE);
                         } else {
                             showDialog(DIALOG_NEED_LOCKSCREEN);
                         }
@@ -466,22 +474,6 @@
         }
     }
 
-    private UserInfo createRestrictedProfile() {
-        UserInfo newUserInfo = mUserManager.createRestrictedProfile(mAddingUserName);
-        if (newUserInfo != null && !assignDefaultPhoto(getActivity(), newUserInfo.id)) {
-            return null;
-        }
-        return newUserInfo;
-    }
-
-    private UserInfo createTrustedUser() {
-        UserInfo newUserInfo = mUserManager.createUser(mAddingUserName, 0);
-        if (newUserInfo != null && !assignDefaultPhoto(getActivity(), newUserInfo.id)) {
-            return null;
-        }
-        return newUserInfo;
-    }
-
     private void onManageUserClicked(int userId, boolean newUser) {
         mAddingUser = false;
         if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
@@ -571,15 +563,13 @@
                 final int messageResId = longMessageDisplayed
                         ? R.string.user_add_user_message_short
                         : R.string.user_add_user_message_long;
-                final int userType = dialogId == DIALOG_ADD_USER
-                        ? USER_TYPE_USER : USER_TYPE_RESTRICTED_PROFILE;
                 Dialog dlg = new AlertDialog.Builder(context)
                         .setTitle(R.string.user_add_user_title)
                         .setMessage(messageResId)
                         .setPositiveButton(android.R.string.ok,
                                 new DialogInterface.OnClickListener() {
                                     public void onClick(DialogInterface dialog, int which) {
-                                        addUserNow(userType);
+                                        showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_USER);
                                         if (!longMessageDisplayed) {
                                             preferences.edit().putBoolean(
                                                     KEY_ADD_USER_LONG_MESSAGE_DISPLAYED,
@@ -675,20 +665,96 @@
                 return dlg;
             }
             case DIALOG_USER_PROFILE_EDITOR: {
-                Dialog dlg = mEditUserInfoController.createDialog(
+                UserHandle user = myUserHandle();
+                UserInfo info = mUserManager.getUserInfo(user.getIdentifier());
+                return mEditUserInfoController.createDialog(
                         this,
-                        null,
-                        mMePreference.getTitle(),
-                        R.string.profile_info_settings_title,
-                        this /* callback */,
-                        android.os.Process.myUserHandle());
-                return dlg;
+                        Utils.getUserIcon(getPrefContext(), mUserManager, info),
+                        info.name,
+                        getString(R.string.profile_info_settings_title),
+                        new EditUserInfoController.OnContentChangedCallback() {
+                            @Override
+                            public void onPhotoChanged(UserHandle user, Drawable photo) {
+                                ThreadUtils.postOnBackgroundThread(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        mUserManager.setUserIcon(user.getIdentifier(),
+                                                UserIcons.convertToBitmap(photo));
+                                    }
+                                });
+                                mMePreference.setIcon(photo);
+                            }
+
+                            @Override
+                            public void onLabelChanged(UserHandle user, CharSequence label) {
+                                mMePreference.setTitle(label.toString());
+                                mUserManager.setUserName(user.getIdentifier(), label.toString());
+                            }
+                        },
+                        user,
+                        null);
+            }
+            case DIALOG_USER_PROFILE_EDITOR_ADD_USER: {
+                synchronized (mUserLock) {
+                    mPendingUserIcon = UserIcons.getDefaultUserIcon(getPrefContext().getResources(),
+                            new Random(System.currentTimeMillis()).nextInt(8), false);
+                    mPendingUserName = getString(R.string.user_new_user_name);
+                }
+                return buildAddUserProfileEditorDialog(USER_TYPE_USER);
+            }
+            case DIALOG_USER_PROFILE_EDITOR_ADD_RESTRICTED_PROFILE: {
+                synchronized (mUserLock) {
+                    mPendingUserIcon = UserIcons.getDefaultUserIcon(getPrefContext().getResources(),
+                            new Random(System.currentTimeMillis()).nextInt(8), false);
+                    mPendingUserName = getString(R.string.user_new_profile_name);
+                }
+                return buildAddUserProfileEditorDialog(USER_TYPE_RESTRICTED_PROFILE);
             }
             default:
                 return null;
         }
     }
 
+    private Dialog buildAddUserProfileEditorDialog(int userType) {
+        Dialog d;
+        synchronized (mUserLock) {
+            d = mEditUserInfoController.createDialog(
+                    this,
+                    mPendingUserIcon,
+                    mPendingUserName,
+                    getString(userType == USER_TYPE_USER
+                            ? R.string.user_info_settings_title
+                            : R.string.profile_info_settings_title),
+                    new EditUserInfoController.OnContentChangedCallback() {
+                        @Override
+                        public void onPhotoChanged(UserHandle user, Drawable photo) {
+                            mPendingUserIcon = photo;
+                        }
+
+                        @Override
+                        public void onLabelChanged(UserHandle user, CharSequence label) {
+                            mPendingUserName = label;
+                        }
+                    },
+                    myUserHandle(),
+                    new EditUserInfoController.OnDialogCompleteCallback() {
+                        @Override
+                        public void onPositive() {
+                            addUserNow(userType);
+                        }
+
+                        @Override
+                        public void onNegativeOrCancel() {
+                            synchronized (mUserLock) {
+                                mPendingUserIcon = null;
+                                mPendingUserName = null;
+                            }
+                        }
+                    });
+        }
+        return d;
+    }
+
     @Override
     public int getDialogMetricsCategory(int dialogId) {
         switch (dialogId) {
@@ -709,6 +775,8 @@
             case DIALOG_CONFIRM_EXIT_GUEST:
                 return SettingsEnums.DIALOG_USER_CONFIRM_EXIT_GUEST;
             case DIALOG_USER_PROFILE_EDITOR:
+            case DIALOG_USER_PROFILE_EDITOR_ADD_USER:
+            case DIALOG_USER_PROFILE_EDITOR_ADD_RESTRICTED_PROFILE:
                 return SettingsEnums.DIALOG_USER_EDIT_PROFILE;
             default:
                 return 0;
@@ -719,14 +787,15 @@
         if (mRemovingUserId == UserHandle.myUserId()) {
             removeThisUser();
         } else {
-            new Thread() {
+            ThreadUtils.postOnBackgroundThread(new Runnable() {
+                @Override
                 public void run() {
                     synchronized (mUserLock) {
                         mUserManager.removeUser(mRemovingUserId);
                         mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
                     }
                 }
-            }.start();
+            });
         }
     }
 
@@ -746,39 +815,59 @@
     private void addUserNow(final int userType) {
         synchronized (mUserLock) {
             mAddingUser = true;
-            mAddingUserName = userType == USER_TYPE_USER ? getString(R.string.user_new_user_name)
-                    : getString(R.string.user_new_profile_name);
-            //updateUserList();
-            new Thread() {
-                public void run() {
-                    UserInfo user;
-                    // Could take a few seconds
-                    if (userType == USER_TYPE_USER) {
-                        user = createTrustedUser();
-                    } else {
-                        user = createRestrictedProfile();
-                    }
+            mAddingUserName = userType == USER_TYPE_USER
+                    ? (mPendingUserName != null ? mPendingUserName.toString()
+                    : getString(R.string.user_new_user_name))
+                    : (mPendingUserName != null ? mPendingUserName.toString()
+                            : getString(R.string.user_new_profile_name));
+        }
+        ThreadUtils.postOnBackgroundThread(new Runnable() {
+            @Override
+            public void run() {
+                UserInfo user;
+                String username;
+
+                synchronized (mUserLock) {
+                    username = mAddingUserName;
+                }
+
+                // Could take a few seconds
+                if (userType == USER_TYPE_USER) {
+                    user = mUserManager.createUser(username, 0);
+                } else {
+                    user = mUserManager.createRestrictedProfile(username);
+                }
+
+                synchronized (mUserLock) {
                     if (user == null) {
                         mAddingUser = false;
+                        mPendingUserIcon = null;
+                        mPendingUserName = null;
                         return;
                     }
-                    synchronized (mUserLock) {
-                        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));
-                        }
+
+                    if (mPendingUserIcon != null) {
+                        mUserManager.setUserIcon(user.id,
+                                UserIcons.convertToBitmap(mPendingUserIcon));
                     }
+
+                    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));
+                    }
+                    mPendingUserIcon = null;
+                    mPendingUserName = null;
                 }
-            }.start();
-        }
+            }
+        });
     }
 
     private void switchUserNow(int userId) {
@@ -1123,16 +1212,6 @@
         return R.string.help_url_users;
     }
 
-    @Override
-    public void onPhotoChanged(Drawable photo) {
-        mMePreference.setIcon(photo);
-    }
-
-    @Override
-    public void onLabelChanged(CharSequence label) {
-        mMePreference.setTitle(label);
-    }
-
     /**
      * Returns a default user icon (as a {@link Bitmap}) for the given user.
      *
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index ecf20fd..add37dd 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -276,7 +276,7 @@
                 mHiddenSettingsSpinner.getSelectedItemPosition() == NOT_HIDDEN_NETWORK
                         ? View.GONE
                         : View.VISIBLE);
-        mSecurityInPosition = new Integer[WifiEntry.SECURITY_MAX_VAL];
+        mSecurityInPosition = new Integer[WifiEntry.NUM_SECURITY_TYPES];
 
         if (mWifiEntry == null) { // new network
             configureSecuritySpinner();
@@ -411,7 +411,7 @@
                     }
 
                     addRow(group, R.string.wifi_security,
-                            WifiEntryShell.getSecurityString(mWifiEntry, false));
+                            mWifiEntry.getSecurityString(false /* concise */));
                     mView.findViewById(R.id.ip_fields).setVisibility(View.GONE);
                 }
                 if (mWifiEntry.isSaved()
diff --git a/src/com/android/settings/wifi/WifiEntryShell.java b/src/com/android/settings/wifi/WifiEntryShell.java
index 2af0d7b..7c6fc48 100644
--- a/src/com/android/settings/wifi/WifiEntryShell.java
+++ b/src/com/android/settings/wifi/WifiEntryShell.java
@@ -48,13 +48,6 @@
      */
     public static final int HIGHER_FREQ_5GHZ = 5900;
 
-    /**
-     * Mapping of the corresponding {@link AccessPoint} method
-     */
-    public static String getSecurityString(WifiEntry wifiEntry, boolean concise) {
-        return "None";
-    }
-
     // Passpoint methods
 
     /**
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 5193213..b5813cf 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -330,7 +330,7 @@
         mIpv6Category = screen.findPreference(KEY_IPV6_CATEGORY);
         mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
 
-        mSecurityPref.setSummary(WifiEntryShell.getSecurityString(mWifiEntry, /* concise */ false));
+        mSecurityPref.setSummary(mWifiEntry.getSecurityString(false /* concise */));
     }
 
     private void setupEntityHeader(PreferenceScreen screen) {
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 93a3530..51cb351 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -252,11 +252,6 @@
         final WifiConfiguration wifiConfiguration = wifiEntry.getWifiConfiguration();
         setConfiguratorIntentExtra(intent, wifiManager, wifiConfiguration);
 
-        // For a transition mode Wi-Fi AP, creates a QR code that's compatible with more devices
-        if (wifiEntry.getSecurity() == WifiEntry.SECURITY_PSK_SAE_TRANSITION) {
-            intent.putExtra(EXTRA_WIFI_SECURITY, WifiQrCode.SECURITY_WPA_PSK);
-        }
-
         return intent;
     }
 
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index 3c4a001..4665515 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -258,6 +258,12 @@
                 }
 
                 @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return !context.getResources().getBoolean(
+                            R.bool.config_show_all_in_one_tether_settings);
+                }
+
+                @Override
                 public List<AbstractPreferenceController> createPreferenceControllers(
                         Context context) {
                     return buildPreferenceControllers(context, null /* listener */);
diff --git a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
index 51c856a..37a3474 100644
--- a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
@@ -69,18 +69,21 @@
     }
 
     @Test
-    public void getNonIndexableKeys_tetherAvailable_keysNotReturned() {
+    public void getNonIndexableKeys_tetherAvailable_keysReturned() {
         // To let TetherUtil.isTetherAvailable return true, select one of the combinations
         setupIsTetherAvailable(true);
 
         final List<String> niks =
                 AllInOneTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
 
-        assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
-        assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
-        assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
-        assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
-        assertThat(niks).doesNotContain(AllInOneTetherSettings.KEY_TETHER_PREFS_SCREEN);
+        // TODO(b/147675042) Should revert these assertions, after switching to new UI.
+        // Because of the config check, we are not indexing these keys. Once we enable the config
+        // these assert would also need to change.
+        assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
+        assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
+        assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
+        assertThat(niks).contains(AllInOneTetherSettings.KEY_WIFI_TETHER_NETWORK_AP_BAND);
+        assertThat(niks).contains(AllInOneTetherSettings.KEY_TETHER_PREFS_SCREEN);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
index 3aa6a6f..e291a43 100644
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
@@ -25,7 +25,6 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -57,7 +56,6 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
@@ -246,7 +244,6 @@
     @Test
     public void testValidateApnData_validData_shouldReturnNull() {
         // GIVEN a valid apn data
-        mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // WHEN validate the apn data
@@ -259,9 +256,7 @@
     @Test
     public void testValidateApn_apnNameNotSet_shouldReturnErrorMessage() {
         // GIVEN a apn data without the apn name
-        final FakeApnData apnData = new FakeApnData(APN_DATA);
-        apnData.mData[ApnEditor.NAME_INDEX] = "";
-        mApnEditorUT.mApnData = apnData;
+        mApnEditorUT.mApnData.mData[ApnEditor.NAME_INDEX] = "";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // THEN validate the apn data
@@ -274,9 +269,7 @@
     @Test
     public void testValidateApnData_apnNotSet_shouldReturnErrorMessage() {
         // GIVEN a apn data without the apn
-        final FakeApnData apnData = new FakeApnData(APN_DATA);
-        apnData.mData[ApnEditor.APN_INDEX] = "";
-        mApnEditorUT.mApnData = apnData;
+        mApnEditorUT.mApnData.mData[ApnEditor.APN_INDEX] = "";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // THEN validate the apn data
@@ -288,11 +281,8 @@
 
     @Test
     public void testValidateApnData_mccInvalid_shouldReturnErrorMessage() {
-        // GIVEN a apn data with invalid mcc
-        final FakeApnData apnData = new FakeApnData(APN_DATA);
         // The length of the mcc should be 3
-        apnData.mData[ApnEditor.MCC_INDEX] = "1324";
-        mApnEditorUT.mApnData = apnData;
+        mApnEditorUT.mApnData.mData[ApnEditor.MCC_INDEX] = "1324";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // WHEN validate the apn data
@@ -305,10 +295,8 @@
     @Test
     public void testValidateApnData_mncInvalid_shouldReturnErrorMessage() {
         // GIVEN an apn data with invalid mnc
-        final FakeApnData apnData = new FakeApnData(APN_DATA);
         // The length of the mnc should be 2 or 3
-        apnData.mData[ApnEditor.MNC_INDEX] = "1324";
-        mApnEditorUT.mApnData = apnData;
+        mApnEditorUT.mApnData.mData[ApnEditor.MNC_INDEX] = "1324";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // WHEN validate the apn data
@@ -321,7 +309,6 @@
     @Test
     public void testSaveApnData_pressBackButtonWithValidApnData_shouldSaveApnData() {
         // GIVEN a valid apn data
-        mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // WHEN press the back button
@@ -336,7 +323,6 @@
     @Test
     public void testSaveApnData_pressSaveButtonWithValidApnData_shouldSaveApnData() {
         // GIVEN a valid apn data
-        mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // WHEN press the save button
@@ -353,10 +339,8 @@
     @Test
     public void testSaveApnData_apnDataInvalid_shouldNotSaveApnData() {
         // GIVEN an invalid apn data
-        final FakeApnData apnData = new FakeApnData(APN_DATA);
         // The valid apn data should contains a non-empty apn name
-        apnData.mData[ApnEditor.NAME_INDEX] = "";
-        mApnEditorUT.mApnData = apnData;
+        mApnEditorUT.mApnData.mData[ApnEditor.NAME_INDEX] = "";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // WHEN press the save button
@@ -475,19 +459,45 @@
     }
 
     @Test
+    public void getUserEnteredApnProtocol_emptyApnProtocol_shouldReturnDefaultIPv4v6() {
+        // GIVEN read default APN protocol with IPV4V6
+        mApnEditorUT.mDefaultApnProtocol = "IPV4V6";
+
+        // Input empty in TYPE
+        mApnEditorUT.mApnData.mData[ApnEditor.PROTOCOL_INDEX] = "";
+        mApnEditorUT.fillUI(true /* firstTime */);
+
+        // THEN APN type should be IPV4V6
+        assertThat(mApnEditorUT.getUserEnteredApnProtocol(
+                mApnEditorUT.mProtocol, mApnEditorUT.mDefaultApnProtocol))
+                .isEqualTo("IPV4V6");
+    }
+
+    @Test
+    public void getUserEnteredApnProtocol_emptyApnProtocol_shouldReturnDefaultIP() {
+        // GIVEN read default APN protocol with IP
+        mApnEditorUT.mDefaultApnProtocol = "IP";
+
+        // Input empty in TYPE
+        mApnEditorUT.mApnData.mData[ApnEditor.PROTOCOL_INDEX] = "";
+        mApnEditorUT.fillUI(true /* firstTime */);
+
+        // THEN APN type should be IPV4V6
+        assertThat(mApnEditorUT.getUserEnteredApnProtocol(
+                mApnEditorUT.mProtocol, mApnEditorUT.mDefaultApnProtocol))
+                .isEqualTo("IP");
+    }
+
+    @Test
     public void getUserEnteredApnType_emptyApnType_shouldReturnDefault() {
         // case 1
         // GIVEN read only APN types with DUN
-        String[] readOnlyApnTypes = {"dun"};
-        mApnEditorUT.mReadOnlyApnTypes = readOnlyApnTypes;
+        mApnEditorUT.mReadOnlyApnTypes = new String [] {"dun"};
         // GIVEN read specificApnTypeForEmptyInput with DEFAULT,DUN
-        String[] defaultApnTypes = {"default", "dun"};
-        mApnEditorUT.mDefaultApnTypes = defaultApnTypes;
+        mApnEditorUT.mDefaultApnTypes = new String [] {"default", "dun"};
 
         // Input empty in TYPE
-        final FakeApnData apnData = new FakeApnData(APN_DATA);
-        apnData.mData[ApnEditor.TYPE_INDEX] = "";
-        mApnEditorUT.mApnData = apnData;
+        mApnEditorUT.mApnData.mData[ApnEditor.TYPE_INDEX] = "";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // THEN APN type should be default
@@ -495,16 +505,12 @@
 
         // case 2
         // GIVEN read only APN types with DUN
-        String[] readOnlyApnTypesCase2 = {"dun"};
-        mApnEditorUT.mReadOnlyApnTypes = readOnlyApnTypesCase2;
+        mApnEditorUT.mReadOnlyApnTypes = new String [] {"dun"};
         // GIVEN read specificApnTypeForEmptyInput with DEFAULT
-        String[] defaultApnTypesCase2 = {"default"};
-        mApnEditorUT.mDefaultApnTypes = defaultApnTypesCase2;
+        mApnEditorUT.mDefaultApnTypes = new String [] {"default"};
 
         // Input empty in TYPE
-        final FakeApnData apnDataCase2 = new FakeApnData(APN_DATA);
-        apnDataCase2.mData[ApnEditor.TYPE_INDEX] = "";
-        mApnEditorUT.mApnData = apnDataCase2;
+        mApnEditorUT.mApnData.mData[ApnEditor.TYPE_INDEX] = "";
         mApnEditorUT.fillUI(true /* firstTime */);
 
         // THEN APN type should be default
diff --git a/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java b/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java
index a6a76f8..1c191fa 100644
--- a/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java
+++ b/tests/robotests/src/com/android/settings/users/EditUserInfoControllerTest.java
@@ -18,13 +18,16 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Dialog;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.widget.EditText;
@@ -37,9 +40,6 @@
 import com.android.settings.R;
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
 
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -50,6 +50,9 @@
 import org.robolectric.android.controller.ActivityController;
 import org.robolectric.annotation.Config;
 
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 @RunWith(RobolectricTestRunner.class)
 public class EditUserInfoControllerTest {
     private static final int MAX_USER_NAME_LENGTH = 100;
@@ -88,7 +91,8 @@
     @Test
     public void photoControllerOnActivityResult_whenWaiting_isCalled() {
         mController.createDialog(mFragment, mCurrentIcon, "test user",
-                R.string.profile_info_settings_title, null, android.os.Process.myUserHandle());
+                "title", null,
+                android.os.Process.myUserHandle(), null);
         mController.startingActivityForResult();
         Intent resultData = new Intent();
         mController.onActivityResult(0, 0, resultData);
@@ -104,8 +108,8 @@
         final String longName = Stream.generate(
                 () -> String.valueOf('A')).limit(200).collect(Collectors.joining());
         final AlertDialog dialog = (AlertDialog) mController.createDialog(mFragment, mCurrentIcon,
-                "test user", R.string.profile_info_settings_title, null,
-                android.os.Process.myUserHandle());
+                "test user", "title", null,
+                android.os.Process.myUserHandle(), null);
         final EditText userName = ShadowAlertDialogCompat.shadowOf(dialog).getView()
                 .findViewById(R.id.user_name);
 
@@ -113,4 +117,143 @@
 
         assertThat(userName.getText().length()).isEqualTo(MAX_USER_NAME_LENGTH);
     }
+
+    @Test
+    public void onDialogCompleteCallback_isCalled_whenCancelled() {
+        EditUserInfoController.OnContentChangedCallback contentChangeCallback = mock(
+                EditUserInfoController.OnContentChangedCallback.class);
+
+        EditUserInfoController.OnDialogCompleteCallback dialogCompleteCallback = mock(
+                EditUserInfoController.OnDialogCompleteCallback.class);
+
+        AlertDialog dialog = (AlertDialog) mController.createDialog(
+                mFragment, mCurrentIcon, "test",
+                "title", contentChangeCallback,
+                android.os.Process.myUserHandle(),
+                dialogCompleteCallback);
+
+        dialog.show();
+        dialog.cancel();
+
+        verify(contentChangeCallback, times(0))
+                .onLabelChanged(any(), any());
+        verify(contentChangeCallback, times(0))
+                .onPhotoChanged(any(), any());
+        verify(dialogCompleteCallback, times(0)).onPositive();
+        verify(dialogCompleteCallback, times(1)).onNegativeOrCancel();
+    }
+
+    @Test
+    public void onDialogCompleteCallback_isCalled_whenPositiveClicked() {
+        EditUserInfoController.OnContentChangedCallback contentChangeCallback = mock(
+                EditUserInfoController.OnContentChangedCallback.class);
+
+        EditUserInfoController.OnDialogCompleteCallback dialogCompleteCallback = mock(
+                EditUserInfoController.OnDialogCompleteCallback.class);
+
+        AlertDialog dialog = (AlertDialog) mController.createDialog(
+                mFragment, mCurrentIcon, "test",
+                "title", contentChangeCallback,
+                android.os.Process.myUserHandle(),
+                dialogCompleteCallback);
+
+        // No change to the photo.
+        when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(mCurrentIcon);
+
+        dialog.show();
+        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+
+        verify(contentChangeCallback, times(0))
+                .onLabelChanged(any(), any());
+        verify(contentChangeCallback, times(0))
+                .onPhotoChanged(any(), any());
+        verify(dialogCompleteCallback, times(1)).onPositive();
+        verify(dialogCompleteCallback, times(0)).onNegativeOrCancel();
+    }
+
+    @Test
+    public void onDialogCompleteCallback_isCalled_whenNegativeClicked() {
+        EditUserInfoController.OnContentChangedCallback contentChangeCallback = mock(
+                EditUserInfoController.OnContentChangedCallback.class);
+
+        EditUserInfoController.OnDialogCompleteCallback dialogCompleteCallback = mock(
+                EditUserInfoController.OnDialogCompleteCallback.class);
+
+        AlertDialog dialog = (AlertDialog) mController.createDialog(
+                mFragment, mCurrentIcon, "test",
+                "title", contentChangeCallback,
+                android.os.Process.myUserHandle(),
+                dialogCompleteCallback);
+
+        dialog.show();
+        dialog.getButton(Dialog.BUTTON_NEGATIVE).performClick();
+
+        verify(contentChangeCallback, times(0))
+                .onLabelChanged(any(), any());
+        verify(contentChangeCallback, times(0))
+                .onPhotoChanged(any(), any());
+        verify(dialogCompleteCallback, times(0)).onPositive();
+        verify(dialogCompleteCallback, times(1)).onNegativeOrCancel();
+    }
+
+    @Test
+    public void onContentChangedCallback_isCalled_whenLabelChanges() {
+        EditUserInfoController.OnContentChangedCallback contentChangeCallback = mock(
+                EditUserInfoController.OnContentChangedCallback.class);
+
+        EditUserInfoController.OnDialogCompleteCallback dialogCompleteCallback = mock(
+                EditUserInfoController.OnDialogCompleteCallback.class);
+
+        AlertDialog dialog = (AlertDialog) mController.createDialog(
+                mFragment, mCurrentIcon, "test",
+                "title", contentChangeCallback,
+                android.os.Process.myUserHandle(),
+                dialogCompleteCallback);
+
+        // No change to the photo.
+        when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(mCurrentIcon);
+
+        dialog.show();
+        String expectedNewName = "new test user";
+        EditText editText = (EditText) dialog.findViewById(R.id.user_name);
+        editText.setText(expectedNewName);
+
+        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+
+        verify(contentChangeCallback, times(1))
+                .onLabelChanged(any(), eq(expectedNewName));
+        verify(contentChangeCallback, times(0))
+                .onPhotoChanged(any(), any());
+        verify(dialogCompleteCallback, times(1)).onPositive();
+        verify(dialogCompleteCallback, times(0)).onNegativeOrCancel();
+    }
+
+    @Test
+    public void onContentChangedCallback_isCalled_whenPhotoChanges() {
+        EditUserInfoController.OnContentChangedCallback contentChangeCallback = mock(
+                EditUserInfoController.OnContentChangedCallback.class);
+
+        EditUserInfoController.OnDialogCompleteCallback dialogCompleteCallback = mock(
+                EditUserInfoController.OnDialogCompleteCallback.class);
+
+        AlertDialog dialog = (AlertDialog) mController.createDialog(
+                mFragment, mCurrentIcon, "test",
+                "title", contentChangeCallback,
+                android.os.Process.myUserHandle(),
+                dialogCompleteCallback);
+
+        // A different drawable.
+        Drawable newPhoto = mock(Drawable.class);
+        when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(newPhoto);
+
+        dialog.show();
+        dialog.getButton(Dialog.BUTTON_POSITIVE).performClick();
+
+        verify(contentChangeCallback, times(0))
+                .onLabelChanged(any(), any());
+        verify(contentChangeCallback, times(1))
+                .onPhotoChanged(any(), eq(newPhoto));
+        verify(dialogCompleteCallback, times(1)).onPositive();
+        verify(dialogCompleteCallback, times(0)).onNegativeOrCancel();
+    }
 }