Merge "Talkback speaks "work" for work profile app" into rvc-dev
diff --git a/res/drawable/ic_add_40dp.xml b/res/drawable/ic_add_40dp.xml
new file mode 100644
index 0000000..7245823
--- /dev/null
+++ b/res/drawable/ic_add_40dp.xml
@@ -0,0 +1,36 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="40dp"
+        android:height="40dp"
+        android:viewportWidth="20"
+        android:viewportHeight="20"
+        android:tint="?android:attr/colorControlNormal">
+
+    <group
+        android:scaleX="0.5"
+        android:scaleY="0.5"
+        android:pivotX="8"
+        android:pivotY="8">
+
+        <path
+            android:fillColor="@android:color/white"
+            android:pathData="M20,13h-7v7h-2v-7H4v-2h7V4h2v7h7V13z"/>
+
+    </group>
+
+</vector>
+
diff --git a/res/drawable/ic_phone.xml b/res/drawable/ic_phone.xml
new file mode 100644
index 0000000..28f47fd
--- /dev/null
+++ b/res/drawable/ic_phone.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal"
+        android:autoMirrored="true">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36
+            1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1
+            -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45
+            0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_swap.xml b/res/drawable/ic_swap.xml
new file mode 100644
index 0000000..1c43d97
--- /dev/null
+++ b/res/drawable/ic_swap.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M6.99,11L3,15l3.99,4v-3H14v-2H6.99v-3zM21,9l-3.99,-4v3H10v2h7.01v3L21,9z"
+        android:fillColor="#000000"/>
+</vector>
diff --git a/res/layout/preference_animated_image.xml b/res/layout/preference_animated_image.xml
index 305b036..e7d9b52 100644
--- a/res/layout/preference_animated_image.xml
+++ b/res/layout/preference_animated_image.xml
@@ -24,9 +24,10 @@
 
     <ImageView
         android:id="@+id/animated_img"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
+        android:scaleType="fitCenter"
         android:focusable="false"
         android:clickable="false"
         android:adjustViewBounds="true"/>
diff --git a/res/layout/restricted_preference_user_delete_widget.xml b/res/layout/restricted_preference_user_delete_widget.xml
deleted file mode 100644
index 71f1dd7..0000000
--- a/res/layout/restricted_preference_user_delete_widget.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- Used by UserPreference to show the trash icon -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <include layout="@layout/restricted_icon" />
-
-    <LinearLayout android:id="@+id/user_delete_widget"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:orientation="horizontal">
-        <View
-            android:id="@+id/divider_manage"
-            android:layout_width="2dip"
-            android:layout_height="match_parent"
-            android:layout_marginTop="5dip"
-            android:layout_marginBottom="5dip"
-            android:background="@android:drawable/divider_horizontal_dark" />
-        <ImageView
-            android:id="@+id/manage_user"
-            android:layout_width="wrap_content"
-            android:layout_height="fill_parent"
-            android:paddingStart="16dip"
-            android:paddingEnd="16dip"
-            android:src="@drawable/ic_settings_accent"
-            android:contentDescription="@string/settings_label"
-            android:layout_gravity="center"
-            android:background="?android:attr/selectableItemBackground" />
-        <View
-            android:id="@+id/divider_delete"
-            android:layout_width="2dip"
-            android:layout_height="match_parent"
-            android:layout_marginTop="5dip"
-            android:layout_marginBottom="5dip"
-            android:background="@android:drawable/divider_horizontal_dark" />
-        <ImageView
-            android:id="@+id/trash_user"
-            android:layout_width="wrap_content"
-            android:layout_height="fill_parent"
-            android:paddingStart="16dip"
-            android:paddingEnd="16dip"
-            android:src="@drawable/ic_delete"
-            android:contentDescription="@string/user_delete_user_description"
-            android:layout_gravity="center"
-            android:background="?android:attr/selectableItemBackground" />
-    </LinearLayout>
-</merge>
\ No newline at end of file
diff --git a/res/layout/user_info_header.xml b/res/layout/user_info_header.xml
index 5135e0e..bfdf3fc 100644
--- a/res/layout/user_info_header.xml
+++ b/res/layout/user_info_header.xml
@@ -15,6 +15,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
@@ -45,8 +46,7 @@
                 android:layout_gravity="center"
                 android:minWidth="48dp"
                 android:scaleType="centerInside"
-                android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
-                 />
+                android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
         </LinearLayout>
         <RelativeLayout
             android:layout_width="wrap_content"
@@ -60,6 +60,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:singleLine="true"
+                tools:text="Richard"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:ellipsize="marquee"
                 android:fadingEdge="horizontal"/>
@@ -88,6 +89,40 @@
                 android:layout_gravity="center"
                 android:background="?android:attr/selectableItemBackground" />
     </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/switch_pref"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical"
+        android:visibility="gone"
+        tools:visibility="visible"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:background="?android:attr/selectableItemBackground" >
+
+        <ImageView
+            android:id="@+id/switchIcon"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_gravity="center"
+            android:src="@drawable/ic_swap"
+            android:minWidth="48dp"
+            android:scaleType="centerInside"
+            android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
+
+        <TextView
+            android:id="@+id/switchTitle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            tools:text="Switch to Richard"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal"/>
+
+    </LinearLayout>
+
     <View android:layout_width="match_parent"
           android:layout_height="2dp"
           android:background="@color/divider_color" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 244e873..9bc9b5e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4945,7 +4945,7 @@
     <!-- Title for the accessibility tutorial dialog in accessibility service with button. [CHAR LIMIT=50] -->
     <string name="accessibility_tutorial_dialog_title_button">Use accessibility button to open</string>
     <!-- Title for the accessibility tutorial dialog in accessibility service with volume keys. [CHAR LIMIT=50] -->
-    <string name="accessibility_tutorial_dialog_title_volume">Hold volume key to open</string>
+    <string name="accessibility_tutorial_dialog_title_volume">Hold volume keys to open</string>
     <!-- Title for the accessibility tutorial dialog in accessibility service with triple tap. [CHAR LIMIT=100] -->
     <string name="accessibility_tutorial_dialog_title_triple">Triple tap screen to open</string>
     <!-- Title for the accessibility tutorial dialog in accessibility service with gesture. [CHAR LIMIT=50] -->
@@ -4953,19 +4953,19 @@
     <!-- Title for the accessibility tutorial dialog in gesture navigation settings. [CHAR LIMIT=50] -->
     <string name="accessibility_tutorial_dialog_title_gesture_settings">Use new accessibility gesture</string>
     <!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using the 3-button nav bar. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_tutorial_dialog_message_button">To turn this feature on or off, tap the accessibility button <xliff:g id="accessibility_icon" example="[Icon]">%s</xliff:g> on the bottom of your screen.\n\nTo switch between features, touch &amp; hold the accessibility button.</string>
+    <string name="accessibility_tutorial_dialog_message_button">To use this feature, tap the accessibility button <xliff:g id="accessibility_icon" example="[Icon]">%s</xliff:g> on the bottom of your screen.\n\nTo switch between features, touch &amp; hold the accessibility button.</string>
     <!-- Instruction for the accessibility tutorial dialog in accessibility service with volume keys. [CHAR LIMIT=100] -->
-    <string name="accessibility_tutorial_dialog_message_volume">To turn this feature on or off, press &amp; hold both volume keys.</string>
+    <string name="accessibility_tutorial_dialog_message_volume">To use this feature, press &amp; hold both volume keys.</string>
     <!-- Instruction for the accessibility tutorial dialog in accessibility service with triple tap. [CHAR LIMIT=100] -->
     <string name="accessibility_tutorial_dialog_message_triple">To start and stop magnification, triple-tap anywhere on your screen.</string>
     <!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using gesture navigation and touch exploration is not enabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_tutorial_dialog_message_gesture">To turn this feature on or off, swipe up from the bottom of the screen with 2 fingers.\n\nTo switch between features, swipe up with 2 fingers and hold.</string>
+    <string name="accessibility_tutorial_dialog_message_gesture">To use this feature, swipe up from the bottom of the screen with 2 fingers.\n\nTo switch between features, swipe up with 2 fingers and hold.</string>
     <!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using gesture navigation and touch exploration is enabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_tutorial_dialog_message_gesture_talkback">To turn this feature on or off, swipe up from the bottom of the screen with 3 fingers.\n\nTo switch between features, swipe up with 3 fingers and hold.</string>
+    <string name="accessibility_tutorial_dialog_message_gesture_talkback">To use this feature, swipe up from the bottom of the screen with 3 fingers.\n\nTo switch between features, swipe up with 3 fingers and hold.</string>
     <!-- Message for the accessibility tutorial dialog when user chooses gesture navigation in navigation settings, an accessibility service is using the accessibility button, and touch exploration is disabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_tutorial_dialog_message_gesture_settings">To turn an accessibility feature on or off, swipe up from the bottom of the screen with 2 fingers.\n\nTo switch between features, swipe up with 2 fingers and hold.</string>
+    <string name="accessibility_tutorial_dialog_message_gesture_settings">To use an accessibility feature, swipe up from the bottom of the screen with 2 fingers.\n\nTo switch between features, swipe up with 2 fingers and hold.</string>
     <!-- Message for the accessibility tutorial dialog when user chooses gesture navigation in navigation settings, an accessibility service is using the accessibility button, and touch exploration is enabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_tutorial_dialog_message_gesture_settings_talkback">To turn an accessibility feature on or off, swipe up from the bottom of the screen with 3 fingers.\n\nTo switch between features, swipe up with 3 fingers and hold.</string>
+    <string name="accessibility_tutorial_dialog_message_gesture_settings_talkback">To use an accessibility feature, swipe up from the bottom of the screen with 3 fingers.\n\nTo switch between features, swipe up with 3 fingers and hold.</string>
     <!-- Button for the accessibility tutorial dialog to dismiss the dialog when user clicks it. [CHAR LIMIT=10] -->
     <string name="accessibility_tutorial_dialog_button">Got it</string>
     <!-- Title for accessibility shortcut preference for accessibility apps. [CHAR LIMIT=40] -->
@@ -7312,6 +7312,9 @@
     <!-- Summary of multimedia messaging service settings.  [CHAR LIMIT=100] -->
     <string name="mms_message_summary">Send &amp; receive when mobile data is off</string>
 
+    <!-- Cell broacast receiver package name [DO NOT TRANSLATE] -->
+    <string name="cell_broadcast_receiver_package">com.android.cellbroadcastreceiver</string>
+
     <!-- Title of a preference for whether to allow data during calls that is shown when mobile
          data is turned off. This is needed for some multi-SIM scenarios, because the SIM that is
          default for data might not be available during a phone call. [CHAR LIMIT=60] -->
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index f75bd86..b499180 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -82,7 +82,7 @@
         settings:useAdminDisabledSummary="true">
         <intent
             android:action="android.intent.action.MAIN"
-            android:targetPackage="com.android.cellbroadcastreceiver"
+            android:targetPackage="@string/cell_broadcast_receiver_package"
             android:targetClass="com.android.cellbroadcastreceiver.CellBroadcastSettings"/>
     </com.android.settingslib.RestrictedPreference>
 
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index 09154c4..d336395 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -17,12 +17,17 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:settings="http://schemas.android.com/apk/res-auto">
 
+
+    <com.android.settingslib.RestrictedPreference
+            android:key="switch_user"
+            android:icon="@drawable/ic_swap" />
     <SwitchPreference
             android:key="enable_calling"
+            android:icon="@drawable/ic_phone"
             android:title="@string/user_enable_calling_sms" />
     <com.android.settingslib.RestrictedPreference
             android:key="remove_user"
-            android:title="@string/user_remove_user"
+            android:icon="@drawable/ic_delete"
             settings:userRestriction="no_remove_user"
             settings:useAdminDisabledSummary="true" />
 
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index eb8803b..7726a18 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -28,9 +28,14 @@
     </PreferenceCategory>
 
     <com.android.settingslib.RestrictedPreference
+        android:key="guest_add"
+        android:title="@string/guest_new_guest"
+        android:order="15"/>
+
+    <com.android.settingslib.RestrictedPreference
         android:key="user_add"
         android:title="@string/user_add_user_or_profile_menu"
-        android:icon="@drawable/ic_add_24dp"
+        android:icon="@drawable/ic_add_40dp"
         android:order="20"/>
 
     <com.android.settingslib.RestrictedSwitchPreference
diff --git a/src/com/android/settings/accessibility/AnimatedImagePreference.java b/src/com/android/settings/accessibility/AnimatedImagePreference.java
index 61e439f..2ca13f3 100644
--- a/src/com/android/settings/accessibility/AnimatedImagePreference.java
+++ b/src/com/android/settings/accessibility/AnimatedImagePreference.java
@@ -60,7 +60,7 @@
         }
 
         if (mMaxHeight > -1) {
-            imageView.setMaxWidth(mMaxHeight);
+            imageView.setMaxHeight(mMaxHeight);
         }
     }
 
diff --git a/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceController.java b/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceController.java
index 29c6176..ec88ddc 100644
--- a/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceController.java
+++ b/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceController.java
@@ -86,7 +86,7 @@
         final ContentResolver resolver = mContext.getContentResolver();
         boolean cardsAvailable = Settings.Secure.getInt(resolver, CARDS_AVAILABLE_KEY, 0) != 0;
         boolean cardsEnabled = Settings.Secure.getInt(resolver, CARDS_ENABLED_KEY, 0) != 0;
-        boolean controlsEnabled = Settings.Secure.getInt(resolver, CONTROLS_ENABLED_KEY, 0) != 0;
+        boolean controlsEnabled = Settings.Secure.getInt(resolver, CONTROLS_ENABLED_KEY, 1) != 0;
         return (cardsAvailable && cardsEnabled) || controlsEnabled;
     }
 
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index d5a192a..6917549 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -413,10 +413,10 @@
                                 TelephonyManagerConstants.NETWORK_MODE_LTE_GSM_WCDMA);
                         if (is5gEntryDisplayed()) {
                             setSummary(mShow4gForLTE
-                                ? R.string.network_4G_pure : R.string.network_lte_pure);
+                                    ? R.string.network_4G_pure : R.string.network_lte_pure);
                         } else {
                             setSummary(mShow4gForLTE
-                                ? R.string.network_4G : R.string.network_lte);
+                                    ? R.string.network_4G : R.string.network_lte);
                         }
                     } else {
                         setSelectedEntry(
@@ -461,8 +461,8 @@
                 case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
                 case TelephonyManagerConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
                     if (MobileNetworkUtils.isTdscdmaSupported(mContext, mSubId)) {
-                        setSelectedEntry(
-                                TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
+                        setSelectedEntry(TelephonyManagerConstants
+                                .NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
                         setSummary(is5gEntryDisplayed()
                                 ? R.string.network_lte_pure : R.string.network_lte);
                     } else {
@@ -498,8 +498,8 @@
                 case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA:
                 case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA:
                 case TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
-                    setSelectedEntry(
-                        TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
+                    setSelectedEntry(TelephonyManagerConstants
+                            .NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA);
                     setSummary(mContext.getString(R.string.network_5G)
                             + mContext.getString(R.string.network_recommended));
                     break;
@@ -553,7 +553,8 @@
                 case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
                     return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA;
                 case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
-                    return TelephonyManagerConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+                    return TelephonyManagerConstants
+                            .NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
                 default:
                     return networkType; // not LTE
             }
@@ -654,7 +655,7 @@
         }
 
         private String[] getEntryValues() {
-            Integer intArr[] = mEntriesValue.toArray(new Integer[0]);
+            final Integer [] intArr = mEntriesValue.toArray(new Integer[0]);
             return Arrays.stream(intArr)
                     .map(String::valueOf)
                     .toArray(String[]::new);
diff --git a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
index 7add167..de7e780 100644
--- a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
+++ b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
@@ -24,6 +24,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
+import com.android.internal.telephony.CellBroadcastUtils;
 import com.android.settings.accounts.AccountRestrictionHelper;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedPreference;
@@ -88,7 +89,9 @@
                 com.android.internal.R.bool.config_cellBroadcastAppLinks);
         if (enabled) {
             try {
-                if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+                String packageName = CellBroadcastUtils
+                        .getDefaultCellBroadcastReceiverPackageName(mContext);
+                if (packageName == null || mPm.getApplicationEnabledSetting(packageName)
                         == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
                     enabled = false;  // CMAS app disabled
                 }
diff --git a/src/com/android/settings/notification/RemoteVolumeGroupController.java b/src/com/android/settings/notification/RemoteVolumeGroupController.java
index a0b1057..4b045e2 100644
--- a/src/com/android/settings/notification/RemoteVolumeGroupController.java
+++ b/src/com/android/settings/notification/RemoteVolumeGroupController.java
@@ -23,8 +23,6 @@
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.OnLifecycleEvent;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
@@ -32,7 +30,8 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnDestroy;
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
 import com.android.settingslib.media.MediaOutputSliceConstants;
@@ -46,7 +45,8 @@
  * {@link com.android.settings.notification.RemoteVolumeSeekBarPreference}
  **/
 public class RemoteVolumeGroupController extends BasePreferenceController implements
-        Preference.OnPreferenceChangeListener, LifecycleObserver, LocalMediaManager.DeviceCallback {
+        Preference.OnPreferenceChangeListener, LifecycleObserver, OnDestroy,
+        LocalMediaManager.DeviceCallback {
 
     private static final String KEY_REMOTE_VOLUME_GROUP = "remote_media_group";
     private static final String TAG = "RemoteVolumePrefCtr";
@@ -93,11 +93,7 @@
         }
     }
 
-    /**
-     * onDestroy()
-     * {@link androidx.lifecycle.OnLifecycleEvent}
-     **/
-    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+    @Override
     public void onDestroy() {
         mLocalMediaManager.unregisterCallback(this);
         mLocalMediaManager.stopScan();
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 746a2df..9e7f3ed 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -190,7 +190,6 @@
             controller.setCallback(mVolumeCallback);
             getSettingsLifecycle().addObserver(controller);
         }
-        getSettingsLifecycle().addObserver(use(RemoteVolumeGroupController.class));
     }
 
     // === Volumes ===
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index 7b15e8a..1caf49c 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -97,8 +97,15 @@
     /** Key for extra passed in from calling fragment to indicate if this is a newly created user */
     public static final String EXTRA_NEW_USER = "new_user";
 
+    /**
+     * Key for extra passed in from calling fragment to indicate if
+     * switch to user should be shown
+     */
+    public static final String EXTRA_SHOW_SWITCH_USER = "enable_switch";
+
     private boolean mFirstTime = true;
     private boolean mNewUser;
+    protected boolean mShowSwitchUser;
     private boolean mAppListChanged;
     protected boolean mRestrictedProfile;
 
@@ -219,6 +226,7 @@
                     mUser = new UserHandle(args.getInt(EXTRA_USER_ID));
                 }
                 mNewUser = args.getBoolean(EXTRA_NEW_USER, false);
+                mShowSwitchUser = args.getBoolean(EXTRA_SHOW_SWITCH_USER, false);
             }
         }
 
diff --git a/src/com/android/settings/users/RestrictedProfileSettings.java b/src/com/android/settings/users/RestrictedProfileSettings.java
index 57c0d02..44657cf 100644
--- a/src/com/android/settings/users/RestrictedProfileSettings.java
+++ b/src/com/android/settings/users/RestrictedProfileSettings.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.users;
 
+import android.app.ActivityManager;
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.DialogInterface;
@@ -23,7 +24,10 @@
 import android.content.pm.UserInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -36,6 +40,7 @@
 public class RestrictedProfileSettings extends AppRestrictionsFragment
         implements EditUserInfoController.OnContentChangedCallback {
 
+    private static final String TAG = RestrictedProfileSettings.class.getSimpleName();
     public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
     static final int DIALOG_ID_EDIT_USER_INFO = 1;
     private static final int DIALOG_CONFIRM_REMOVE = 2;
@@ -44,6 +49,8 @@
     private ImageView mUserIconView;
     private TextView mUserNameView;
     private ImageView mDeleteButton;
+    private View mSwitchUserView;
+    private TextView mSwitchTitle;
 
     private EditUserInfoController mEditUserInfoController =
             new EditUserInfoController();
@@ -67,6 +74,11 @@
         mUserNameView = (TextView) mHeaderView.findViewById(android.R.id.title);
         mDeleteButton = (ImageView) mHeaderView.findViewById(R.id.delete);
         mDeleteButton.setOnClickListener(this);
+
+        mSwitchTitle = mHeaderView.findViewById(R.id.switchTitle);
+        mSwitchUserView = mHeaderView.findViewById(R.id.switch_pref);
+        mSwitchUserView.setOnClickListener(v -> switchUser());
+
         // This is going to bind the preferences.
         super.onActivityCreated(savedInstanceState);
     }
@@ -80,7 +92,6 @@
     @Override
     public void onResume() {
         super.onResume();
-
         // Check if user still exists
         UserInfo info = Utils.getExistingUser(mUserManager, mUser);
         if (info == null) {
@@ -89,6 +100,16 @@
             ((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
             ((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
                     com.android.settingslib.Utils.getUserIcon(getActivity(), mUserManager, info));
+
+            boolean canSwitchUser =
+                    mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
+            if (mShowSwitchUser && canSwitchUser) {
+                mSwitchUserView.setVisibility(View.VISIBLE);
+                mSwitchTitle.setText(getString(com.android.settingslib.R.string.user_switch_to_user,
+                        info.name));
+            } else {
+                mSwitchUserView.setVisibility(View.GONE);
+            }
         }
     }
 
@@ -158,6 +179,16 @@
         });
     }
 
+    private void switchUser() {
+        try {
+            ActivityManager.getService().switchUser(mUser.getIdentifier());
+        } catch (RemoteException re) {
+            Log.e(TAG, "Error while switching to other user.");
+        } finally {
+            finishFragment();
+        }
+    }
+
     @Override
     public void onPhotoChanged(UserHandle user, Drawable photo) {
         mUserIconView.setImageDrawable(photo);
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 371c152..2696ddc 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -16,55 +16,63 @@
 
 package com.android.settings.users;
 
+import static android.os.UserHandle.USER_NULL;
+
+import android.app.ActivityManager;
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.pm.UserInfo;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 
 import java.util.List;
 
 /**
- * Settings screen for configuring a specific user. It can contain user restrictions
- * and deletion controls. It is shown when you tap on the settings icon in the
- * user management (UserSettings) screen.
+ * Settings screen for configuring, deleting or switching to a specific user.
+ * It is shown when you tap on a user in the user management (UserSettings) screen.
  *
  * Arguments to this fragment must include the userId of the user (in EXTRA_USER_ID) for whom
- * to display controls, or should contain the EXTRA_USER_GUEST = true.
+ * to display controls.
  */
 public class UserDetailsSettings extends SettingsPreferenceFragment
         implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
 
     private static final String TAG = UserDetailsSettings.class.getSimpleName();
 
+    private static final String KEY_SWITCH_USER = "switch_user";
     private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
     private static final String KEY_REMOVE_USER = "remove_user";
 
     /** Integer extra containing the userId to manage */
     static final String EXTRA_USER_ID = "user_id";
-    /** Boolean extra to indicate guest preferences */
-    static final String EXTRA_USER_GUEST = "guest_user";
 
     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 UserManager mUserManager;
+    @VisibleForTesting
+    Preference mSwitchUserPref;
     private SwitchPreference mPhonePref;
-    private Preference mRemoveUserPref;
+    @VisibleForTesting
+    Preference mRemoveUserPref;
 
-    private UserInfo mUserInfo;
-    private boolean mGuestUser;
+    @VisibleForTesting
+    UserInfo mUserInfo;
     private Bundle mDefaultGuestRestrictions;
 
     @Override
@@ -78,46 +86,28 @@
 
         final Context context = getActivity();
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-
         addPreferencesFromResource(R.xml.user_details_settings);
-        mPhonePref = (SwitchPreference) findPreference(KEY_ENABLE_TELEPHONY);
-        mRemoveUserPref = findPreference(KEY_REMOVE_USER);
 
-        mGuestUser = getArguments().getBoolean(EXTRA_USER_GUEST, false);
+        initialize(context, getArguments());
+    }
 
-        if (!mGuestUser) {
-            // Regular user. Get the user id from the caller.
-            final int userId = getArguments().getInt(EXTRA_USER_ID, -1);
-            if (userId == -1) {
-                throw new RuntimeException("Arguments to this fragment must contain the user id");
-            }
-            mUserInfo = mUserManager.getUserInfo(userId);
-            mPhonePref.setChecked(!mUserManager.hasUserRestriction(
-                    UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
-            mRemoveUserPref.setOnPreferenceClickListener(this);
-        } else {
-            // These are not for an existing user, just general Guest settings.
-            removePreference(KEY_REMOVE_USER);
-            // Default title is for calling and SMS. Change to calling-only here
-            mPhonePref.setTitle(R.string.user_enable_calling);
-            mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
-            mPhonePref.setChecked(
-                    !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
-        }
-        if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
-                UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
-            removePreference(KEY_REMOVE_USER);
-        }
-        mPhonePref.setOnPreferenceChangeListener(this);
+    @Override
+    public void onResume() {
+        super.onResume();
+        mSwitchUserPref.setEnabled(canSwitchUserNow());
     }
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
         if (preference == mRemoveUserPref) {
-            if (!mUserManager.isAdminUser()) {
-                throw new RuntimeException("Only admins can remove a user");
+            if (canDeleteUser()) {
+                showDialog(DIALOG_CONFIRM_REMOVE);
             }
-            showDialog(DIALOG_CONFIRM_REMOVE);
+            return true;
+        } else if (preference == mSwitchUserPref) {
+            if (canSwitchUserNow()) {
+                switchUser();
+            }
             return true;
         }
         return false;
@@ -126,7 +116,7 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (Boolean.TRUE.equals(newValue)) {
-            showDialog(mGuestUser ? DIALOG_CONFIRM_ENABLE_CALLING
+            showDialog(mUserInfo.isGuest() ? DIALOG_CONFIRM_ENABLE_CALLING
                     : DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
             return false;
         }
@@ -134,65 +124,6 @@
         return true;
     }
 
-    void enableCallsAndSms(boolean enabled) {
-        mPhonePref.setChecked(enabled);
-        if (mGuestUser) {
-            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled);
-            // SMS is always disabled for guest
-            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
-            mUserManager.setDefaultGuestRestrictions(mDefaultGuestRestrictions);
-
-            // Update the guest's restrictions, if there is a guest
-            // TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
-            // on any existing guest rather than do it here with multiple Binder calls.
-            List<UserInfo> users = mUserManager.getUsers(true);
-            for (UserInfo user: users) {
-                if (user.isGuest()) {
-                    UserHandle userHandle = UserHandle.of(user.id);
-                    for (String key : mDefaultGuestRestrictions.keySet()) {
-                        mUserManager.setUserRestriction(
-                                key, mDefaultGuestRestrictions.getBoolean(key), userHandle);
-                    }
-                }
-            }
-        } else {
-            UserHandle userHandle = UserHandle.of(mUserInfo.id);
-            mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled,
-                    userHandle);
-            mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle);
-        }
-    }
-
-    @Override
-    public Dialog onCreateDialog(int dialogId) {
-        Context context = getActivity();
-        if (context == null) return null;
-        switch (dialogId) {
-            case DIALOG_CONFIRM_REMOVE:
-                return UserDialogs.createRemoveDialog(getActivity(), mUserInfo.id,
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                removeUser();
-                            }
-                        });
-            case DIALOG_CONFIRM_ENABLE_CALLING:
-                return UserDialogs.createEnablePhoneCallsDialog(getActivity(),
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                enableCallsAndSms(true);
-                            }
-                        });
-            case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
-                return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(),
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                enableCallsAndSms(true);
-                            }
-                        });
-        }
-        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
-    }
-
     @Override
     public int getDialogMetricsCategory(int dialogId) {
         switch (dialogId) {
@@ -207,7 +138,148 @@
         }
     }
 
-    void removeUser() {
+    @Override
+    public Dialog onCreateDialog(int dialogId) {
+        Context context = getActivity();
+        if (context == null) {
+            return null;
+        }
+        switch (dialogId) {
+            case DIALOG_CONFIRM_REMOVE:
+                return UserDialogs.createRemoveDialog(getActivity(), mUserInfo.id,
+                        (dialog, which) -> removeUser());
+            case DIALOG_CONFIRM_ENABLE_CALLING:
+                return UserDialogs.createEnablePhoneCallsDialog(getActivity(),
+                        (dialog, which) -> enableCallsAndSms(true));
+            case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
+                return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(),
+                        (dialog, which) -> enableCallsAndSms(true));
+        }
+        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+    }
+
+    @VisibleForTesting
+    @Override
+    protected void showDialog(int dialogId) {
+        super.showDialog(dialogId);
+    }
+
+    @VisibleForTesting
+    void initialize(Context context, Bundle arguments) {
+        int userId = arguments != null ? arguments.getInt(EXTRA_USER_ID, USER_NULL) : USER_NULL;
+        if (userId == USER_NULL) {
+            throw new IllegalStateException("Arguments to this fragment must contain the user id");
+        }
+        mUserInfo = mUserManager.getUserInfo(userId);
+
+        mSwitchUserPref = findPreference(KEY_SWITCH_USER);
+        mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
+        mRemoveUserPref = findPreference(KEY_REMOVE_USER);
+
+        mSwitchUserPref.setTitle(
+                context.getString(com.android.settingslib.R.string.user_switch_to_user,
+                        mUserInfo.name));
+        mSwitchUserPref.setOnPreferenceClickListener(this);
+
+        if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
+            removePreference(KEY_ENABLE_TELEPHONY);
+            removePreference(KEY_REMOVE_USER);
+        } else {
+            if (!Utils.isVoiceCapable(context)) { // no telephony
+                removePreference(KEY_ENABLE_TELEPHONY);
+            }
+
+            if (!mUserInfo.isGuest()) {
+                mPhonePref.setChecked(!mUserManager.hasUserRestriction(
+                        UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
+                mRemoveUserPref.setTitle(R.string.user_remove_user);
+            } else {
+                // These are not for an existing user, just general Guest settings.
+                // Default title is for calling and SMS. Change to calling-only here
+                mPhonePref.setTitle(R.string.user_enable_calling);
+                mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
+                mPhonePref.setChecked(
+                        !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+                mRemoveUserPref.setTitle(R.string.user_exit_guest_title);
+            }
+            if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
+                    UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
+                removePreference(KEY_REMOVE_USER);
+            }
+
+            mRemoveUserPref.setOnPreferenceClickListener(this);
+            mPhonePref.setOnPreferenceChangeListener(this);
+        }
+    }
+
+    @VisibleForTesting
+    boolean canDeleteUser() {
+        if (!mUserManager.isAdminUser()) {
+            return false;
+        }
+
+        Context context = getActivity();
+        if (context == null) {
+            return false;
+        }
+
+        final RestrictedLockUtils.EnforcedAdmin removeDisallowedAdmin =
+                RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
+                        UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
+        if (removeDisallowedAdmin != null) {
+            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context,
+                    removeDisallowedAdmin);
+            return false;
+        }
+        return true;
+    }
+
+    @VisibleForTesting
+    boolean canSwitchUserNow() {
+        return mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
+    }
+
+    @VisibleForTesting
+    void switchUser() {
+        try {
+            ActivityManager.getService().switchUser(mUserInfo.id);
+        } catch (RemoteException re) {
+            Log.e(TAG, "Error while switching to other user.");
+        } finally {
+            finishFragment();
+        }
+    }
+
+    private void enableCallsAndSms(boolean enabled) {
+        mPhonePref.setChecked(enabled);
+        if (mUserInfo.isGuest()) {
+            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled);
+            // SMS is always disabled for guest
+            mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
+            mUserManager.setDefaultGuestRestrictions(mDefaultGuestRestrictions);
+
+            // Update the guest's restrictions, if there is a guest
+            // TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
+            // on any existing guest rather than do it here with multiple Binder calls.
+            List<UserInfo> users = mUserManager.getUsers(true);
+            for (UserInfo user : users) {
+                if (user.isGuest()) {
+                    UserHandle userHandle = UserHandle.of(user.id);
+                    for (String key : mDefaultGuestRestrictions.keySet()) {
+                        mUserManager.setUserRestriction(
+                                key, mDefaultGuestRestrictions.getBoolean(key), userHandle);
+                    }
+                }
+            }
+        } else {
+            UserHandle userHandle = UserHandle.of(mUserInfo.id);
+            mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled,
+                    userHandle);
+            mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle);
+        }
+    }
+
+    private void removeUser() {
         mUserManager.removeUser(mUserInfo.id);
         finishFragment();
     }
diff --git a/src/com/android/settings/users/UserPreference.java b/src/com/android/settings/users/UserPreference.java
index 3603d44..0b78d78 100644
--- a/src/com/android/settings/users/UserPreference.java
+++ b/src/com/android/settings/users/UserPreference.java
@@ -21,18 +21,16 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.AttributeSet;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
 
 import androidx.preference.PreferenceViewHolder;
 
-import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 import java.util.Comparator;
 
+/**
+ * Preference for a user that appear on {@link UserSettings} screen.
+ */
 public class UserPreference extends RestrictedPreference {
     private static final int ALPHA_ENABLED = 255;
     private static final int ALPHA_DISABLED = 102;
@@ -44,8 +42,7 @@
 
                 if (p1 == null) {
                     return -1;
-                }
-                else if (p2 == null) {
+                } else if (p2 == null) {
                     return 1;
                 }
                 int sn1 = p1.getSerialNumber();
@@ -58,26 +55,15 @@
                 return 0;
             };
 
-    private OnClickListener mDeleteClickListener;
-    private OnClickListener mSettingsClickListener;
     private int mSerialNumber = -1;
     private int mUserId = USERID_UNKNOWN;
-    static final int SETTINGS_ID = R.id.manage_user;
-    static final int DELETE_ID = R.id.trash_user;
 
     public UserPreference(Context context, AttributeSet attrs) {
-        this(context, attrs, USERID_UNKNOWN, null, null);
+        this(context, attrs, USERID_UNKNOWN);
     }
 
-    UserPreference(Context context, AttributeSet attrs, int userId,
-            OnClickListener settingsListener,
-            OnClickListener deleteListener) {
+    UserPreference(Context context, AttributeSet attrs, int userId) {
         super(context, attrs);
-        if (deleteListener != null || settingsListener != null) {
-            setWidgetLayoutResource(R.layout.restricted_preference_user_delete_widget);
-        }
-        mDeleteClickListener = deleteListener;
-        mSettingsClickListener = settingsListener;
         mUserId = userId;
         useAdminDisabledSummary(true);
     }
@@ -92,62 +78,13 @@
 
     @Override
     protected boolean shouldHideSecondTarget() {
-        if (isDisabledByAdmin()) {
-            // Disabled by admin, show no secondary target.
-            return true;
-        }
-        if (canDeleteUser()) {
-            // Need to show delete user target so don't hide.
-            return false;
-        }
-        // Hide if don't have advanced setting listener.
-        return mSettingsClickListener == null;
+        return true;
     }
 
     @Override
     public void onBindViewHolder(PreferenceViewHolder view) {
         super.onBindViewHolder(view);
-        final boolean disabledByAdmin = isDisabledByAdmin();
-        dimIcon(disabledByAdmin);
-        View userDeleteWidget = view.findViewById(R.id.user_delete_widget);
-        if (userDeleteWidget != null) {
-            userDeleteWidget.setVisibility(disabledByAdmin ? View.GONE : View.VISIBLE);
-        }
-        if (!disabledByAdmin) {
-            View deleteDividerView = view.findViewById(R.id.divider_delete);
-            View manageDividerView = view.findViewById(R.id.divider_manage);
-            View deleteView = view.findViewById(R.id.trash_user);
-            if (deleteView != null) {
-                if (canDeleteUser()) {
-                    deleteView.setVisibility(View.VISIBLE);
-                    deleteDividerView.setVisibility(View.VISIBLE);
-                    deleteView.setOnClickListener(mDeleteClickListener);
-                    deleteView.setTag(this);
-                } else {
-                    deleteView.setVisibility(View.GONE);
-                    deleteDividerView.setVisibility(View.GONE);
-                }
-            }
-            ImageView manageView = (ImageView) view.findViewById(R.id.manage_user);
-            if (manageView != null) {
-                if (mSettingsClickListener != null) {
-                    manageView.setVisibility(View.VISIBLE);
-                    manageDividerView.setVisibility(mDeleteClickListener == null
-                            ? View.VISIBLE : View.GONE);
-                    manageView.setOnClickListener(mSettingsClickListener);
-                    manageView.setTag(this);
-                } else {
-                    manageView.setVisibility(View.GONE);
-                    manageDividerView.setVisibility(View.GONE);
-                }
-            }
-        }
-    }
-
-    private boolean canDeleteUser() {
-        return mDeleteClickListener != null
-                && !RestrictedLockUtilsInternal.hasBaseUserRestriction(getContext(),
-                UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
+        dimIcon(isDisabledByAdmin());
     }
 
     private int getSerialNumber() {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 38ef199..7d4ab5d 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -48,7 +48,6 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.View;
 import android.widget.SimpleAdapter;
 
 import androidx.annotation.VisibleForTesting;
@@ -69,7 +68,6 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SwitchBar;
 import com.android.settings.widget.SwitchBarController;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
@@ -89,15 +87,14 @@
 
 /**
  * Screen that manages the list of users on the device.
- * Guest user is an always visible entry, even if the guest is not currently
- * active/created. It is meant for controlling properties of a guest user.
+ * Secondary users and a guest user can be created if there is no restriction.
  *
- * The first one is always the current user.
+ * The first user in the list is always the current user.
  * Owner is the primary user.
  */
 @SearchIndexable
 public class UserSettings extends SettingsPreferenceFragment
-        implements Preference.OnPreferenceClickListener, View.OnClickListener,
+        implements Preference.OnPreferenceClickListener,
         MultiUserSwitchBarController.OnMultiUserSwitchChangedListener,
         DialogInterface.OnDismissListener {
 
@@ -111,6 +108,7 @@
     private static final String KEY_USER_LIST = "user_list";
     private static final String KEY_USER_ME = "user_me";
     private static final String KEY_USER_GUEST = "user_guest";
+    private static final String KEY_ADD_GUEST = "guest_add";
     private static final String KEY_ADD_USER = "user_add";
     private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
     private static final String KEY_MULTIUSER_FOOTER = "multiuser_footer";
@@ -156,7 +154,11 @@
     @VisibleForTesting
     UserPreference mMePreference;
     @VisibleForTesting
+    RestrictedPreference mAddGuest;
+    @VisibleForTesting
     RestrictedPreference mAddUser;
+    @VisibleForTesting
+    SparseArray<Bitmap> mUserIcons = new SparseArray<>();
     private int mRemovingUserId = -1;
     private int mAddedUserId = 0;
     private boolean mAddingUser;
@@ -165,7 +167,6 @@
     private boolean mShouldUpdateUserList = true;
     private final Object mUserLock = new Object();
     private UserManager mUserManager;
-    private SparseArray<Bitmap> mUserIcons = new SparseArray<>();
     private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
 
     private MultiUserSwitchBarController mSwitchBarController;
@@ -271,15 +272,17 @@
         final int myUserId = UserHandle.myUserId();
 
         mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
-        mMePreference = new UserPreference(getPrefContext(), null /* attrs */, myUserId,
-                null /* settings icon handler */,
-                null /* delete icon handler */);
+        mMePreference = new UserPreference(getPrefContext(), null /* attrs */, myUserId);
         mMePreference.setKey(KEY_USER_ME);
         mMePreference.setOnPreferenceClickListener(this);
         if (mUserCaps.mIsAdmin) {
             mMePreference.setSummary(R.string.user_admin);
         }
-        mAddUser = (RestrictedPreference) findPreference(KEY_ADD_USER);
+
+        mAddGuest = findPreference(KEY_ADD_GUEST);
+        mAddGuest.setOnPreferenceClickListener(this);
+
+        mAddUser = findPreference(KEY_ADD_USER);
         if (!mUserCaps.mCanAddRestrictedProfile) {
             // Label should only mention adding a "user", not a "profile"
             mAddUser.setTitle(R.string.user_add_user_menu);
@@ -344,8 +347,7 @@
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         int pos = 0;
-        final boolean canSwitchUsers = mUserManager.canSwitchUsers();
-        if (!mUserCaps.mIsAdmin && canSwitchUsers) {
+        if (!mUserCaps.mIsAdmin && canSwitchUserNow()) {
             String nickname = mUserManager.getUserName();
             MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
                     getResources().getString(R.string.user_remove_user_menu, nickname));
@@ -386,10 +388,13 @@
      * Loads profile information for the current user.
      */
     private void loadProfile() {
-        if (mUserCaps.mIsGuest) {
+        if (isCurrentUserGuest()) {
             // No need to load profile information
             mMePreference.setIcon(getEncircledDefaultIcon());
             mMePreference.setTitle(R.string.user_exit_guest_title);
+            mMePreference.setSelectable(true);
+            // removing a guest will result in switching back to the admin user
+            mMePreference.setEnabled(canSwitchUserNow());
             return;
         }
 
@@ -412,7 +417,9 @@
     }
 
     private void finishLoadProfile(String profileName) {
-        if (getActivity() == null) return;
+        if (getActivity() == null) {
+            return;
+        }
         mMePreference.setTitle(getString(R.string.user_you, profileName));
         int myUserId = UserHandle.myUserId();
         Bitmap b = mUserManager.getUserIcon(myUserId);
@@ -477,38 +484,28 @@
 
     private void onManageUserClicked(int userId, boolean newUser) {
         mAddingUser = false;
-        if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
-            Bundle extras = new Bundle();
-            extras.putBoolean(UserDetailsSettings.EXTRA_USER_GUEST, true);
-            new SubSettingLauncher(getContext())
-                    .setDestination(UserDetailsSettings.class.getName())
-                    .setArguments(extras)
-                    .setTitleRes(R.string.user_guest)
-                    .setSourceMetricsCategory(getMetricsCategory())
-                    .launch();
-            return;
-        }
-        UserInfo info = mUserManager.getUserInfo(userId);
-        if (info.isRestricted() && mUserCaps.mIsAdmin) {
+        UserInfo userInfo = mUserManager.getUserInfo(userId);
+        if (userInfo.isRestricted() && mUserCaps.mIsAdmin) {
             Bundle extras = new Bundle();
             extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
             extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
+            extras.putBoolean(RestrictedProfileSettings.EXTRA_SHOW_SWITCH_USER, canSwitchUserNow());
             new SubSettingLauncher(getContext())
                     .setDestination(RestrictedProfileSettings.class.getName())
                     .setArguments(extras)
                     .setTitleRes(R.string.user_restrictions_title)
                     .setSourceMetricsCategory(getMetricsCategory())
                     .launch();
-        } else if (info.id == UserHandle.myUserId()) {
+        } else if (userId == UserHandle.myUserId()) {
             // Jump to owner info panel
             OwnerInfoSettings.show(this);
-        } else if (mUserCaps.mIsAdmin) {
-            final Bundle extras = new Bundle();
+        } else {
+            Bundle extras = new Bundle();
             extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
             new SubSettingLauncher(getContext())
                     .setDestination(UserDetailsSettings.class.getName())
                     .setArguments(extras)
-                    .setTitleText(info.name)
+                    .setTitleText(userInfo.name)
                     .setSourceMetricsCategory(getMetricsCategory())
                     .launch();
         }
@@ -538,7 +535,9 @@
     @Override
     public Dialog onCreateDialog(int dialogId) {
         Context context = getActivity();
-        if (context == null) return null;
+        if (context == null) {
+            return null;
+        }
         switch (dialogId) {
             case DIALOG_CONFIRM_REMOVE: {
                 Dialog dlg =
@@ -811,7 +810,7 @@
     }
 
     private void removeThisUser() {
-        if (!mUserManager.canSwitchUsers()) {
+        if (!canSwitchUserNow()) {
             Log.w(TAG, "Cannot remove current user when switching is disabled");
             return;
         }
@@ -882,10 +881,14 @@
     }
 
     private void switchUserNow(int userId) {
+        if (!canSwitchUserNow()) {
+            return;
+        }
+
         try {
             ActivityManager.getService().switchUser(userId);
         } catch (RemoteException re) {
-            // Nothing to do
+            Log.e(TAG, "Error while switching to other user.");
         }
     }
 
@@ -894,7 +897,7 @@
      */
     private void exitGuest() {
         // Just to be safe
-        if (!mUserCaps.mIsGuest) {
+        if (!isCurrentUserGuest()) {
             return;
         }
         removeThisUser();
@@ -908,12 +911,12 @@
         }
         final List<UserInfo> users = mUserManager.getUsers(true);
 
-        final boolean voiceCapable = Utils.isVoiceCapable(context);
         final ArrayList<Integer> missingIcons = new ArrayList<>();
         final ArrayList<UserPreference> userPreferences = new ArrayList<>();
-        int guestId = UserPreference.USERID_GUEST_DEFAULTS;
         userPreferences.add(mMePreference);
 
+        boolean canOpenUserDetails =
+                mUserCaps.mIsAdmin || (canSwitchUserNow() && !mUserCaps.mDisallowSwitchUser);
         for (UserInfo user : users) {
             if (!user.supportsSwitchToByUser()) {
                 // Only users that can be switched to should show up here.
@@ -924,37 +927,38 @@
             if (user.id == UserHandle.myUserId()) {
                 pref = mMePreference;
             } else if (user.isGuest()) {
-                // Skip over Guest. We add generic Guest settings after this loop
-                guestId = user.id;
-                continue;
+                pref = new UserPreference(getPrefContext(), null, user.id);
+                pref.setTitle(R.string.user_guest);
+                pref.setIcon(getEncircledDefaultIcon());
+                pref.setKey(KEY_USER_GUEST);
+                userPreferences.add(pref);
+                pref.setEnabled(canOpenUserDetails);
+                pref.setSelectable(true);
+
+                if (mUserCaps.mDisallowSwitchUser) {
+                    pref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context));
+                } else {
+                    pref.setDisabledByAdmin(null);
+                }
+                pref.setOnPreferenceClickListener(this);
             } else {
-                // With Telephony:
-                //   Secondary user: Settings
-                //   Guest: Settings
-                //   Restricted Profile: There is no Restricted Profile
-                // Without Telephony:
-                //   Secondary user: Delete
-                //   Guest: Nothing
-                //   Restricted Profile: Settings
-                final boolean showSettings = mUserCaps.mIsAdmin
-                        && (voiceCapable || user.isRestricted());
-                final boolean showDelete = mUserCaps.mIsAdmin
-                        && (!voiceCapable && !user.isRestricted() && !user.isGuest());
-                pref = new UserPreference(getPrefContext(), null, user.id,
-                        showSettings ? this : null,
-                        showDelete ? this : null);
+                pref = new UserPreference(getPrefContext(), null, user.id);
                 pref.setKey("id=" + user.id);
                 userPreferences.add(pref);
                 if (user.isAdmin()) {
                     pref.setSummary(R.string.user_admin);
                 }
                 pref.setTitle(user.name);
-                pref.setSelectable(false);
+                pref.setOnPreferenceClickListener(this);
+                pref.setEnabled(canOpenUserDetails);
+                pref.setSelectable(true);
             }
             if (pref == null) {
                 continue;
             }
-            if (!isInitialized(user)) {
+            if (user.id != UserHandle.myUserId() && !user.isGuest() && !user.isInitialized()) {
+                // sometimes after creating a guest the initialized flag isn't immediately set
+                // and we don't want to show "Not set up" summary for them
                 if (user.isRestricted()) {
                     pref.setSummary(R.string.user_summary_restricted_not_set_up);
                 } else {
@@ -962,10 +966,7 @@
                 }
                 // Disallow setting up user which results in user switching when the restriction is
                 // set.
-                if (!mUserCaps.mDisallowSwitchUser) {
-                    pref.setOnPreferenceClickListener(this);
-                    pref.setSelectable(mUserManager.canSwitchUsers());
-                }
+                pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
             } else if (user.isRestricted()) {
                 pref.setSummary(R.string.user_summary_restricted_profile);
             }
@@ -986,53 +987,13 @@
         // Add a temporary entry for the user being created
         if (mAddingUser) {
             UserPreference pref = new UserPreference(getPrefContext(), null,
-                    UserPreference.USERID_UNKNOWN, null, null);
+                    UserPreference.USERID_UNKNOWN);
             pref.setEnabled(false);
             pref.setTitle(mAddingUserName);
             pref.setIcon(getEncircledDefaultIcon());
             userPreferences.add(pref);
         }
 
-        // Check if Guest tile should be added.
-        if (!mUserCaps.mIsGuest && (mUserCaps.mCanAddGuest ||
-                mUserCaps.mDisallowAddUserSetByAdmin)) {
-            // Add a virtual Guest user for guest defaults
-            UserPreference pref = new UserPreference(getPrefContext(), null,
-                    UserPreference.USERID_GUEST_DEFAULTS,
-                    mUserCaps.mIsAdmin && voiceCapable ? this : null /* settings icon handler */,
-                    null /* delete icon handler */);
-            pref.setTitle(R.string.user_guest);
-            pref.setIcon(getEncircledDefaultIcon());
-            pref.setKey(KEY_USER_GUEST);
-            userPreferences.add(pref);
-            if (mUserCaps.mDisallowAddUser) {
-                pref.setDisabledByAdmin(mUserCaps.mEnforcedAdmin);
-            } else if (mUserCaps.mDisallowSwitchUser) {
-                pref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context));
-            } else {
-                pref.setDisabledByAdmin(null);
-            }
-            if (!mUserManager.canSwitchUsers()) {
-                pref.setSelectable(false);
-            }
-            int finalGuestId = guestId;
-            pref.setOnPreferenceClickListener(preference -> {
-                int id = finalGuestId;
-                if (id == UserPreference.USERID_GUEST_DEFAULTS) {
-                    UserInfo guest = mUserManager.createGuest(
-                            getContext(), preference.getTitle().toString());
-                    if (guest != null) {
-                        id = guest.id;
-                    }
-                }
-                try {
-                    ActivityManager.getService().switchUser(id);
-                } catch (RemoteException e) {
-                    e.rethrowFromSystemServer();
-                }
-                return true;
-            });
-        }
 
         // Sort list of users by serialNum
         Collections.sort(userPreferences, UserPreference.SERIAL_NUMBER_COMPARATOR);
@@ -1064,6 +1025,7 @@
         mMultiUserFooterPreferenceController.updateState(multiUserFooterPrefence);
         mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled);
 
+        updateAddGuest(context, users.stream().anyMatch(UserInfo::isGuest));
         updateAddUser(context);
 
         if (!mUserCaps.mUserSwitcherEnabled) {
@@ -1077,15 +1039,38 @@
 
     }
 
+    private boolean isCurrentUserGuest() {
+        return mUserCaps.mIsGuest;
+    }
+
+    private boolean canSwitchUserNow() {
+        return mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
+    }
+
+    private void updateAddGuest(Context context, boolean isGuestAlreadyCreated) {
+        if (!isGuestAlreadyCreated && mUserCaps.mCanAddGuest
+                && WizardManagerHelper.isDeviceProvisioned(context)
+                && mUserCaps.mUserSwitcherEnabled) {
+            mAddGuest.setVisible(true);
+            mAddGuest.setIcon(getEncircledDefaultIcon());
+            mAddGuest.setEnabled(canSwitchUserNow());
+            mAddGuest.setSelectable(true);
+        } else {
+            mAddGuest.setVisible(false);
+        }
+    }
+
     private void updateAddUser(Context context) {
         if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin)
                 && WizardManagerHelper.isDeviceProvisioned(context)
                 && mUserCaps.mUserSwitcherEnabled) {
             mAddUser.setVisible(true);
-            final boolean moreUsers = mUserManager.canAddMoreUsers();
-            mAddUser.setEnabled(moreUsers && !mAddingUser && mUserManager.canSwitchUsers());
-            if (!moreUsers) {
-                mAddUser.setSummary(getString(R.string.user_add_max_count, getMaxRealUsers()));
+            mAddUser.setSelectable(true);
+            final boolean canAddMoreUsers = mUserManager.canAddMoreUsers();
+            mAddUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow());
+            if (!canAddMoreUsers) {
+                mAddUser.setSummary(
+                        getString(R.string.user_add_max_count, getRealUsersCount()));
             } else {
                 mAddUser.setSummary(null);
             }
@@ -1098,18 +1083,15 @@
         }
     }
 
-    private int getMaxRealUsers() {
-        // guest is not counted against getMaxSupportedUsers() number
-        final int maxUsersAndGuest = UserManager.getMaxSupportedUsers() + 1;
-        final List<UserInfo> users = mUserManager.getUsers();
-        // managed profiles are counted against getMaxSupportedUsers()
-        int managedProfiles = 0;
-        for (UserInfo user : users) {
-            if (user.isManagedProfile()) {
-                managedProfiles++;
-            }
-        }
-        return maxUsersAndGuest - managedProfiles;
+    /**
+     * @return number of non-guest non-managed users
+     */
+    @VisibleForTesting
+    int getRealUsersCount() {
+        return (int) mUserManager.getUsers()
+                .stream()
+                .filter(user -> !user.isGuest() && !user.isProfile())
+                .count();
     }
 
     private void loadIconsAsync(List<Integer> missingIcons) {
@@ -1151,12 +1133,12 @@
     @Override
     public boolean onPreferenceClick(Preference pref) {
         if (pref == mMePreference) {
-            if (mUserCaps.mIsGuest) {
+            if (isCurrentUserGuest()) {
                 showDialog(DIALOG_CONFIRM_EXIT_GUEST);
                 return true;
             }
             // If this is a limited user, launch the user info settings instead of profile editor
-            if (mUserManager.isLinkedUser()) {
+            if (mUserManager.isRestrictedProfile()) {
                 onManageUserClicked(UserHandle.myUserId(), false);
             } else {
                 showDialog(DIALOG_USER_PROFILE_EDITOR);
@@ -1165,9 +1147,11 @@
             int userId = ((UserPreference) pref).getUserId();
             // Get the latest status of the user
             UserInfo user = mUserManager.getUserInfo(userId);
-            if (!isInitialized(user)) {
+            if (!user.isInitialized()) {
                 mHandler.sendMessage(mHandler.obtainMessage(
                         MESSAGE_SETUP_USER, user.id, user.serialNumber));
+            } else {
+                onManageUserClicked(userId, false);
             }
         } else if (pref == mAddUser) {
             // If we allow both types, show a picker, otherwise directly go to
@@ -1177,40 +1161,20 @@
             } else {
                 onAddUserClicked(USER_TYPE_USER);
             }
+        } else if (pref == mAddGuest) {
+            UserInfo guest = mUserManager.createGuest(
+                    getContext(), getString(com.android.settingslib.R.string.user_guest));
+            switchUserNow(guest.id);
         }
         return false;
     }
 
-    private boolean isInitialized(UserInfo user) {
-        return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
-    }
-
     private Drawable encircle(Bitmap icon) {
         Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
         return circled;
     }
 
     @Override
-    public void onClick(View v) {
-        if (v.getTag() instanceof UserPreference) {
-            int userId = ((UserPreference) v.getTag()).getUserId();
-            if (v.getId() == UserPreference.DELETE_ID) {
-                final EnforcedAdmin removeDisallowedAdmin =
-                        RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getContext(),
-                                UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
-                if (removeDisallowedAdmin != null) {
-                    RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
-                            removeDisallowedAdmin);
-                } else {
-                    onRemoveUserClicked(userId);
-                }
-            } else if (v.getId() == UserPreference.SETTINGS_ID) {
-                onManageUserClicked(userId, false);
-            }
-        }
-    }
-
-    @Override
     public void onDismiss(DialogInterface dialog) {
         synchronized (mUserLock) {
             mRemovingUserId = -1;
diff --git a/tests/robotests/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceControllerTest.java
index 7891d2f..32048a1 100644
--- a/tests/robotests/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/PowerMenuPrivacyPreferenceControllerTest.java
@@ -202,4 +202,14 @@
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.DISABLED_DEPENDENT_SETTING);
     }
+
+    @Test
+    public void getAvailabilityStatus_controlsDeletedSecure_retursAvailable() {
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+
+        Settings.Secure.putString(mContentResolver, CONTROLS_ENABLED_KEY, null);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index 659c5de..1d4f201 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UserIdInt;
 import android.content.pm.UserInfo;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManager.EnforcingUser;
@@ -43,13 +44,17 @@
 
     private static boolean sIsSupportsMultipleUsers;
 
-    private final List<String> mRestrictions = new ArrayList<>();
+    private final List<String> mBaseRestrictions = new ArrayList<>();
+    private final List<String> mGuestRestrictions = new ArrayList<>();
     private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
     private final List<UserInfo> mUserProfileInfos = new ArrayList<>();
     private final Set<Integer> mManagedProfiles = new HashSet<>();
     private boolean mIsQuietModeEnabled = false;
     private int[] profileIdsForUser = new int[0];
     private boolean mUserSwitchEnabled;
+
+    private @UserManager.UserSwitchabilityResult int mSwitchabilityStatus =
+            UserManager.SWITCHABILITY_STATUS_OK;
     private final Map<Integer, Integer> mSameProfileGroupIds = Maps.newHashMap();
 
     public void addProfile(UserInfo userInfo) {
@@ -82,11 +87,22 @@
 
     @Implementation
     protected boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
-        return mRestrictions.contains(restrictionKey);
+        return mBaseRestrictions.contains(restrictionKey);
     }
 
     public void addBaseUserRestriction(String restriction) {
-        mRestrictions.add(restriction);
+        mBaseRestrictions.add(restriction);
+    }
+
+    @Implementation
+    protected Bundle getDefaultGuestRestrictions() {
+        Bundle bundle = new Bundle();
+        mGuestRestrictions.forEach(restriction -> bundle.putBoolean(restriction, true));
+        return bundle;
+    }
+
+    public void addGuestUserRestriction(String restriction) {
+        mGuestRestrictions.add(restriction);
     }
 
     public static ShadowUserManager getShadow() {
@@ -166,4 +182,21 @@
     public void setSupportsMultipleUsers(boolean supports) {
         sIsSupportsMultipleUsers = supports;
     }
+
+    @Implementation
+    protected UserInfo getUserInfo(@UserIdInt int userId) {
+        return mUserProfileInfos.stream()
+                .filter(userInfo -> userInfo.id == userId)
+                .findFirst()
+                .orElse(super.getUserInfo(userId));
+    }
+
+    @Implementation
+    protected @UserManager.UserSwitchabilityResult int getUserSwitchability() {
+        return mSwitchabilityStatus;
+    }
+
+    public void setSwitchabilityStatus(@UserManager.UserSwitchabilityResult int newStatus) {
+        mSwitchabilityStatus = newStatus;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
new file mode 100644
index 0000000..6c54782
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.users;
+
+import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
+import static android.os.UserManager.SWITCHABILITY_STATUS_USER_IN_CALL;
+import static android.os.UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.telephony.TelephonyManager;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        ShadowUserManager.class,
+        ShadowDevicePolicyManager.class
+})
+public class UserDetailsSettingsTest {
+
+    private static final String KEY_SWITCH_USER = "switch_user";
+    private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
+    private static final String KEY_REMOVE_USER = "remove_user";
+
+    private static final int DIALOG_CONFIRM_REMOVE = 1;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+
+    private ShadowUserManager mUserManager;
+
+    @Mock
+    private Preference mSwitchUserPref;
+    @Mock
+    private SwitchPreference mPhonePref;
+    @Mock
+    private Preference mRemoveUserPref;
+
+    private FragmentActivity mActivity;
+    private Context mContext;
+    private UserDetailsSettings mFragment;
+    private Bundle mArguments;
+    private UserInfo mUserInfo;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mActivity = spy(ActivityController.of(new FragmentActivity()).get());
+        mContext = spy(RuntimeEnvironment.application);
+        mFragment = spy(new UserDetailsSettings());
+        mArguments = new Bundle();
+
+        UserManager userManager = (UserManager) mContext.getSystemService(
+                Context.USER_SERVICE);
+        mUserManager = Shadow.extract(userManager);
+
+        doReturn(mTelephonyManager).when(mActivity).getSystemService(Context.TELEPHONY_SERVICE);
+
+        ReflectionHelpers.setField(mFragment, "mUserManager", userManager);
+        doReturn(mActivity).when(mFragment).getActivity();
+        doReturn(mContext).when(mFragment).getContext();
+
+        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+        doReturn("").when(mActivity).getString(anyInt(), anyString());
+
+        doReturn(mSwitchUserPref).when(mFragment).findPreference(KEY_SWITCH_USER);
+        doReturn(mPhonePref).when(mFragment).findPreference(KEY_ENABLE_TELEPHONY);
+        doReturn(mRemoveUserPref).when(mFragment).findPreference(KEY_REMOVE_USER);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowUserManager.reset();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void initialize_nullArguments_shouldThrowException() {
+        mFragment.initialize(mActivity, null);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void initialize_emptyArguments_shouldThrowException() {
+        mFragment.initialize(mActivity, new Bundle());
+    }
+
+    @Test
+    public void initialize_userSelected_shouldSetupSwitchPref() {
+        setupSelectedUser();
+        doReturn("Switch to " + mUserInfo.name)
+                .when(mActivity).getString(anyInt(), anyString());
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mActivity).getString(com.android.settingslib.R.string.user_switch_to_user,
+                mUserInfo.name);
+        verify(mSwitchUserPref).setTitle("Switch to " + mUserInfo.name);
+        verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
+        verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
+    }
+
+    @Test
+    public void initialize_guestSelected_shouldSetupSwitchPref() {
+        setupSelectedGuest();
+        doReturn("Switch to " + mUserInfo.name)
+                .when(mActivity).getString(anyInt(), anyString());
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mActivity).getString(com.android.settingslib.R.string.user_switch_to_user,
+                mUserInfo.name);
+        verify(mSwitchUserPref).setTitle("Switch to " + mUserInfo.name);
+        verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
+        verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
+    }
+
+    @Test
+    public void onResume_canSwitch_shouldEnableSwitchPref() {
+        mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.onAttach(mContext);
+
+        mFragment.onResume();
+
+        verify(mSwitchUserPref).setEnabled(true);
+    }
+
+    @Test
+    public void onResume_userInCall_shouldDisableSwitchPref() {
+        mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_IN_CALL);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.onAttach(mContext);
+
+        mFragment.onResume();
+
+        verify(mSwitchUserPref).setEnabled(false);
+    }
+
+    @Test
+    public void onResume_switchDisallowed_shouldDisableSwitchPref() {
+        mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.onAttach(mContext);
+
+        mFragment.onResume();
+
+        verify(mSwitchUserPref).setEnabled(false);
+    }
+
+    @Test
+    public void onResume_systemUserLocked_shouldDisableSwitchPref() {
+        mUserManager.setSwitchabilityStatus(UserManager.SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.onAttach(mContext);
+
+        mFragment.onResume();
+
+        verify(mSwitchUserPref).setEnabled(false);
+    }
+
+    @Test
+    public void initialize_adminWithTelephony_shouldShowPhonePreference() {
+        setupSelectedUser();
+        doReturn(true).when(mTelephonyManager).isVoiceCapable();
+        mUserManager.setIsAdminUser(true);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mFragment, never()).removePreference(KEY_ENABLE_TELEPHONY);
+        verify(mPhonePref).setOnPreferenceChangeListener(mFragment);
+    }
+
+    @Test
+    public void initialize_adminNoTelephony_shouldNotShowPhonePreference() {
+        setupSelectedUser();
+        doReturn(false).when(mTelephonyManager).isVoiceCapable();
+        mUserManager.setIsAdminUser(true);
+        doReturn(null).when(mActivity).getSystemService(Context.TELEPHONY_SERVICE);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
+    }
+
+    @Test
+    public void initialize_nonAdminWithTelephony_shouldNotShowPhonePreference() {
+        setupSelectedUser();
+        doReturn(true).when(mTelephonyManager).isVoiceCapable();
+        mUserManager.setIsAdminUser(false);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
+    }
+
+    @Test
+    public void initialize_adminSelectsSecondaryUser_shouldShowRemovePreference() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(true);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mRemoveUserPref).setOnPreferenceClickListener(mFragment);
+        verify(mRemoveUserPref).setTitle(R.string.user_remove_user);
+        verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
+    }
+
+    @Test
+    public void initialize_adminSelectsGuest_shouldShowRemovePreference() {
+        setupSelectedGuest();
+        mUserManager.setIsAdminUser(true);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mRemoveUserPref).setOnPreferenceClickListener(mFragment);
+        verify(mRemoveUserPref).setTitle(R.string.user_exit_guest_title);
+        verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
+    }
+
+    @Test
+    public void initialize_nonAdmin_shouldNotShowRemovePreference() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(false);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mFragment).removePreference(KEY_REMOVE_USER);
+    }
+
+    @Test
+    public void initialize_disallowRemoveUserRestriction_shouldNotShowRemovePreference() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(true);
+        mUserManager.addBaseUserRestriction(UserManager.DISALLOW_REMOVE_USER);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mFragment).removePreference(KEY_REMOVE_USER);
+    }
+
+    @Test
+    public void initialize_userHasCallRestriction_shouldSetPhoneSwitchUnChecked() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(true);
+        mUserManager.setUserRestriction(mUserInfo.getUserHandle(),
+                UserManager.DISALLOW_OUTGOING_CALLS, true);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mPhonePref).setChecked(false);
+    }
+
+    @Test
+    public void initialize_noCallRestriction_shouldSetPhoneSwitchChecked() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(true);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mPhonePref).setChecked(true);
+    }
+
+    @Test
+    public void initialize_guestSelected_noCallRestriction_shouldSetPhonePreference() {
+        setupSelectedGuest();
+        mUserManager.setIsAdminUser(true);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mPhonePref).setTitle(R.string.user_enable_calling);
+        verify(mPhonePref).setChecked(true);
+    }
+
+    @Test
+    public void initialize_guestSelected_callRestriction_shouldSetPhonePreference() {
+        setupSelectedGuest();
+        mUserManager.setIsAdminUser(true);
+        mUserManager.addGuestUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
+
+        mFragment.initialize(mActivity, mArguments);
+
+        verify(mPhonePref).setTitle(R.string.user_enable_calling);
+        verify(mPhonePref).setChecked(false);
+    }
+
+    @Test
+    public void onPreferenceClick_switchClicked_canSwitch_shouldSwitch() {
+        setupSelectedUser();
+        mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        mFragment.mUserInfo = mUserInfo;
+
+        mFragment.onPreferenceClick(mSwitchUserPref);
+
+        verify(mFragment).switchUser();
+    }
+
+    @Test
+    public void onPreferenceClick_switchClicked_canNotSwitch_doNothing() {
+        setupSelectedUser();
+        mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        mFragment.mUserInfo = mUserInfo;
+
+        mFragment.onPreferenceClick(mSwitchUserPref);
+
+        verify(mFragment, never()).switchUser();
+    }
+
+    @Test
+    public void onPreferenceClick_removeClicked_canDelete_shouldShowDialog() {
+        setupSelectedUser();
+        mFragment.mUserInfo = mUserInfo;
+        mUserManager.setIsAdminUser(true);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        doNothing().when(mFragment).showDialog(anyInt());
+
+        mFragment.onPreferenceClick(mRemoveUserPref);
+
+        verify(mFragment).canDeleteUser();
+        verify(mFragment).showDialog(DIALOG_CONFIRM_REMOVE);
+    }
+
+    @Test
+    public void onPreferenceClick_removeClicked_canNotDelete_doNothing() {
+        setupSelectedUser();
+        mFragment.mUserInfo = mUserInfo;
+        mUserManager.setIsAdminUser(false);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        doNothing().when(mFragment).showDialog(anyInt());
+
+        mFragment.onPreferenceClick(mRemoveUserPref);
+
+        verify(mFragment).canDeleteUser();
+        verify(mFragment, never()).showDialog(DIALOG_CONFIRM_REMOVE);
+    }
+
+    @Test
+    public void onPreferenceClick_unknownPreferenceClicked_doNothing() {
+        setupSelectedUser();
+        mFragment.mUserInfo = mUserInfo;
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+
+        mFragment.onPreferenceClick(mock(UserPreference.class));
+
+        verify(mFragment).onPreferenceClick(any());
+        verifyNoMoreInteractions(mFragment);
+    }
+
+    @Test
+    public void canDeleteUser_nonAdminUser_shouldReturnFalse() {
+        mUserManager.setIsAdminUser(false);
+
+        boolean result = mFragment.canDeleteUser();
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void canDeleteUser_adminSelectsUser_noRestrictions_shouldReturnTrue() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(true);
+
+        boolean result = mFragment.canDeleteUser();
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void canDeleteUser_adminSelectsUser_hasRemoveRestriction_shouldReturnFalse() {
+        setupSelectedUser();
+        mUserManager.setIsAdminUser(true);
+        ComponentName componentName = new ComponentName("test", "test");
+        ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(componentName);
+        ShadowDevicePolicyManager.getShadow().setDeviceOwnerUserId(UserHandle.myUserId());
+        List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
+        enforcingUsers.add(new UserManager.EnforcingUser(UserHandle.myUserId(),
+                UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
+        mUserManager.setUserRestrictionSources(
+                UserManager.DISALLOW_REMOVE_USER,
+                UserHandle.of(UserHandle.myUserId()),
+                enforcingUsers
+        );
+
+        boolean result = mFragment.canDeleteUser();
+
+        assertThat(result).isFalse();
+    }
+
+    private void setupSelectedUser() {
+        mArguments.putInt("user_id", 1);
+        mUserInfo = new UserInfo(1, "Tom", null,
+                UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED,
+                UserManager.USER_TYPE_FULL_SECONDARY);
+
+        mUserManager.addProfile(mUserInfo);
+    }
+
+    private void setupSelectedGuest() {
+        mArguments.putInt("user_id", 23);
+        mUserInfo = new UserInfo(23, "Guest", null,
+                UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_GUEST,
+                UserManager.USER_TYPE_FULL_GUEST);
+
+        mUserManager.addProfile(mUserInfo);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java b/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java
index 345784a..28f415e 100644
--- a/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java
@@ -18,12 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
 import android.content.Context;
 import android.os.UserHandle;
-import android.view.View;
 
 import com.android.settingslib.RestrictedPreferenceHelper;
 
@@ -48,28 +44,12 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mUserPreference = new UserPreference(mContext, null /* attrs */, UserHandle.USER_CURRENT,
-                null /* settingsListener */, null /* deleteListener */);
+        mUserPreference = new UserPreference(mContext, null /* attrs */, UserHandle.USER_CURRENT);
         ReflectionHelpers.setField(mUserPreference, "mHelper", mRestrictedPreferenceHelper);
     }
 
     @Test
-    public void testShouldHideSecondTarget_noListener_shouldHide() {
+    public void testShouldHideSecondTarget_shouldHide() {
         assertThat(mUserPreference.shouldHideSecondTarget()).isTrue();
     }
-
-    @Test
-    public void testShouldHideSecondTarget_disabledByAdmin_shouldHide() {
-        when(mRestrictedPreferenceHelper.isDisabledByAdmin()).thenReturn(true);
-
-        assertThat(mUserPreference.shouldHideSecondTarget()).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSecondTarget_hasSettingListener_shouldNotHide() {
-        ReflectionHelpers.setField(mUserPreference, "mSettingsClickListener",
-                mock(View.OnClickListener.class));
-
-        assertThat(mUserPreference.shouldHideSecondTarget()).isFalse();
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
index 5853308..3104c3c 100644
--- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
@@ -16,9 +16,14 @@
 
 package com.android.settings.users;
 
+import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
+import static android.os.UserManager.SWITCHABILITY_STATUS_USER_IN_CALL;
+import static android.os.UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.notNull;
@@ -26,12 +31,14 @@
 import static org.mockito.Mockito.mock;
 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.mockito.Mockito.when;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -42,14 +49,13 @@
 import android.view.MenuItem;
 
 import androidx.fragment.app.FragmentActivity;
-import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 
 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;
@@ -57,6 +63,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.AdditionalMatchers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -65,6 +72,7 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -73,7 +81,18 @@
 public class UserSettingsTest {
 
     private static final String KEY_USER_GUEST = "user_guest";
-    private int mProvisioned;
+    private static final int ACTIVE_USER_ID = 0;
+    private static final int INACTIVE_ADMIN_USER_ID = 1;
+    private static final int INACTIVE_SECONDARY_USER_ID = 14;
+    private static final int INACTIVE_RESTRICTED_USER_ID = 21;
+    private static final int INACTIVE_GUEST_USER_ID = 23;
+    private static final int MANAGED_USER_ID = 11;
+    private static final String ADMIN_USER_NAME = "Owner";
+    private static final String SECONDARY_USER_NAME = "Tom";
+    private static final String RESTRICTED_USER_NAME = "Bob";
+    private static final String GUEST_USER_NAME = "Guest";
+    private static final String MANAGED_USER_NAME = "Work profile";
+    private int mProvisionedBackupValue;
 
     @Mock
     private Drawable mDefaultIconDrawable;
@@ -82,6 +101,10 @@
     @Mock
     private UserPreference mMePreference;
     @Mock
+    private RestrictedPreference mAddUserPreference;
+    @Mock
+    private RestrictedPreference mAddGuestPreference;
+    @Mock
     private UserManager mUserManager;
 
     private FragmentActivity mActivity;
@@ -95,6 +118,7 @@
         mActivity = spy(ActivityController.of(new FragmentActivity()).get());
         mContext = spy(RuntimeEnvironment.application);
         mUserCapabilities = UserCapabilities.create(mContext);
+        mUserCapabilities.mUserSwitcherEnabled = true;
 
         mFragment = spy(new UserSettings());
         ReflectionHelpers.setField(mFragment, "mAddUserWhenLockedPreferenceController",
@@ -105,100 +129,41 @@
         ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
         ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
         ReflectionHelpers.setField(mFragment, "mAddingUser", false);
-        mFragment.mMePreference = mMePreference;
 
-        when((Object) mActivity.getSystemService(UserManager.class)).thenReturn(mUserManager);
+        doReturn(mUserManager).when(mActivity).getSystemService(UserManager.class);
+
         doReturn(mActivity).when(mFragment).getActivity();
         doReturn(mContext).when(mFragment).getContext();
         doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
         doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
-        mProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
-            Settings.Global.DEVICE_PROVISIONED, 0);
-        final SharedPreferences prefs = mock(SharedPreferences .class);
-        when(mMockPreferenceManager.getSharedPreferences()).thenReturn(prefs);
-        when(mMockPreferenceManager.getContext()).thenReturn(mContext);
+
+        mProvisionedBackupValue = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 1); //default state
+
+        final SharedPreferences prefs = mock(SharedPreferences.class);
+
+        doReturn(prefs).when(mMockPreferenceManager).getSharedPreferences();
+        doReturn(mContext).when(mMockPreferenceManager).getContext();
+        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+
+        mFragment.mMePreference = mMePreference;
+        mFragment.mAddUser = mAddUserPreference;
+        mFragment.mAddGuest = mAddGuestPreference;
+        mFragment.mUserListCategory = mock(PreferenceCategory.class);
     }
 
     @After
     public void tearDown() {
         Settings.Global.putInt(mContext.getContentResolver(),
-            Settings.Global.DEVICE_PROVISIONED, mProvisioned);
+                Settings.Global.DEVICE_PROVISIONED, mProvisionedBackupValue);
     }
 
     @Test
     public void testAssignDefaultPhoto_ContextNull_ReturnFalseAndNotCrash() {
         // Should not crash here
-        assertThat(UserSettings.assignDefaultPhoto(null, 0)).isFalse();
-    }
-
-    @Test
-    public void updateUserList_cannotSwitchUser_shouldNotBeSelectableForGuest() {
-        final RestrictedPreference addUser = spy(new RestrictedPreference(mContext));
-        final PreferenceGroup userListCategory = spy(new PreferenceCategory(mContext));
-
-        mUserCapabilities.mIsGuest = false;
-        mUserCapabilities.mCanAddGuest = true;
-        mUserCapabilities.mDisallowAddUser = false;
-        mUserCapabilities.mDisallowSwitchUser = false;
-        mUserCapabilities.mUserSwitcherEnabled = true;
-
-        mFragment.mUserListCategory = userListCategory;
-        mFragment.mAddUser = addUser;
-
-        when(mUserManager.canSwitchUsers()).thenReturn(false);
-        doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-        doReturn(mMockPreferenceManager).when(userListCategory).getPreferenceManager();
-
-        mFragment.updateUserList();
-
-        final Preference guest = userListCategory.findPreference(KEY_USER_GUEST);
-        assertThat(guest.isSelectable()).isFalse();
-    }
-
-    @Test
-    public void updateUserList_cannotSwitchUser_shouldDisableAddUser() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-            Settings.Global.DEVICE_PROVISIONED, 1);
-        final RestrictedPreference addUser = spy(new RestrictedPreference(mContext));
-        final PreferenceGroup userListCategory = spy(new PreferenceCategory(mContext));
-
-        mUserCapabilities.mCanAddUser = true;
-        mUserCapabilities.mDisallowAddUser = false;
-        mUserCapabilities.mUserSwitcherEnabled = true;
-
-        mFragment.mUserListCategory = userListCategory;
-        mFragment.mAddUser = addUser;
-
-        when(mUserManager.canSwitchUsers()).thenReturn(false);
-        when(mUserManager.canAddMoreUsers()).thenReturn(true);
-        doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-        doReturn(mMockPreferenceManager).when(userListCategory).getPreferenceManager();
-
-        mFragment.updateUserList();
-
-        assertThat(addUser.isEnabled()).isFalse();
-    }
-
-    @Test
-    public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-            Settings.Global.DEVICE_PROVISIONED, 1);
-        final RestrictedPreference addUser = mock(RestrictedPreference.class);
-
-        mUserCapabilities.mCanAddUser = false;
-        mUserCapabilities.mDisallowAddUser = true;
-        mUserCapabilities.mUserSwitcherEnabled = true;
-
-        mFragment.mUserListCategory = mock(PreferenceCategory.class);
-        mFragment.mAddUser = addUser;
-
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-
-        mFragment.updateUserList();
-
-        verify(addUser, never()).setVisible(true);
+        assertThat(UserSettings.assignDefaultPhoto(null, ACTIVE_USER_ID)).isFalse();
     }
 
     @Test
@@ -218,7 +183,7 @@
         ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(
                 new ComponentName("test", "test"));
 
-        doReturn(true).when(mUserManager).canSwitchUsers();
+        doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
         mUserCapabilities.mIsAdmin = false;
 
         Menu menu = mock(Menu.class);
@@ -243,7 +208,7 @@
     @Test
     public void withoutDisallowRemoveUser_ShouldNotDisableRemoveUser() {
         // Arrange
-        doReturn(true).when(mUserManager).canSwitchUsers();
+        doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
         mUserCapabilities.mIsAdmin = false;
 
         Menu menu = mock(Menu.class);
@@ -266,44 +231,458 @@
 
     @Test
     public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-            Settings.Global.DEVICE_PROVISIONED, 1);
-        final RestrictedPreference addUser = mock(RestrictedPreference.class);
-
         mUserCapabilities.mCanAddUser = true;
-        mUserCapabilities.mDisallowAddUser = false;
-        mUserCapabilities.mUserSwitcherEnabled = true;
-
-        mFragment.mAddUser = addUser;
-        mFragment.mUserListCategory = mock(PreferenceCategory.class);
-
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-        doReturn("Test summary").when(mFragment).getString(anyInt(), anyInt());
+        doReturn(true).when(mUserManager).canAddMoreUsers();
+        doReturn(true).when(mAddUserPreference).isEnabled();
+        doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
 
         mFragment.updateUserList();
 
-        verify(addUser).setVisible(true);
+        verify(mAddUserPreference).setVisible(true);
+        verify(mAddUserPreference).setSummary(null);
+        verify(mAddUserPreference).setEnabled(true);
+        verify(mAddUserPreference).setDisabledByAdmin(null);
+        verify(mAddUserPreference).setSelectable(true);
     }
 
     @Test
-    public void updateUserList_addUserDisallowedByAdmin_shouldShowAddUserDisabled() {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        final RestrictedPreference addUser = mock(RestrictedPreference.class);
-
-        mUserCapabilities.mCanAddUser = false;
-        mUserCapabilities.mDisallowAddUser = true;
-        mUserCapabilities.mDisallowAddUserSetByAdmin = true;
-        mUserCapabilities.mUserSwitcherEnabled = true;
-
-        mFragment.mUserListCategory = mock(PreferenceCategory.class);
-        mFragment.mAddUser = addUser;
-
-        doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+    public void updateUserList_canAddGuestAndSwitchUser_shouldShowAddGuest() {
+        mUserCapabilities.mCanAddGuest = true;
+        doReturn(true).when(mUserManager).canAddMoreUsers();
+        doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
 
         mFragment.updateUserList();
 
-        verify(addUser).setVisible(true);
-        assertThat(addUser.isEnabled()).isFalse();
+        verify(mAddGuestPreference).setVisible(true);
+        verify(mAddGuestPreference).setEnabled(true);
+        verify(mAddGuestPreference).setIcon(any(Drawable.class));
+        verify(mAddGuestPreference).setSelectable(true);
     }
+
+    @Test
+    public void updateUserList_cannotSwitchUser_shouldDisableAddUser() {
+        mUserCapabilities.mCanAddUser = true;
+        doReturn(true).when(mUserManager).canAddMoreUsers();
+        doReturn(true).when(mAddUserPreference).isEnabled();
+        doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED)
+                .when(mUserManager).getUserSwitchability();
+
+        mFragment.updateUserList();
+
+        verify(mAddUserPreference).setVisible(true);
+        verify(mAddUserPreference).setSummary(null);
+        verify(mAddUserPreference).setEnabled(false);
+        verify(mAddUserPreference).setSelectable(true);
+    }
+
+    @Test
+    public void updateUserList_canNotAddMoreUsers_shouldDisableAddUserWithSummary() {
+        mUserCapabilities.mCanAddUser = true;
+        doReturn(false).when(mUserManager).canAddMoreUsers();
+        doReturn(false).when(mAddUserPreference).isEnabled();
+        doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
+        doReturn(4).when(mFragment).getRealUsersCount();
+
+        mFragment.updateUserList();
+
+        verify(mAddUserPreference).setVisible(true);
+        verify(mAddUserPreference).setSummary("You can add up to 4 users");
+        verify(mAddUserPreference).setEnabled(false);
+        verify(mAddUserPreference).setSelectable(true);
+    }
+
+    @Test
+    public void updateUserList_cannotSwitchUser_shouldDisableAddGuest() {
+        mUserCapabilities.mCanAddGuest = true;
+        doReturn(true).when(mUserManager).canAddMoreUsers();
+        doReturn(SWITCHABILITY_STATUS_USER_IN_CALL).when(mUserManager).getUserSwitchability();
+
+        mFragment.updateUserList();
+
+        verify(mAddGuestPreference).setVisible(true);
+        verify(mAddGuestPreference).setEnabled(false);
+        verify(mAddGuestPreference).setIcon(any(Drawable.class));
+        verify(mAddGuestPreference).setSelectable(true);
+    }
+
+    @Test
+    public void updateUserList_addUserDisallowedByAdmin_shouldShowDisabledAddUser() {
+        RestrictedLockUtils.EnforcedAdmin enforcedAdmin = mock(
+                RestrictedLockUtils.EnforcedAdmin.class);
+        mUserCapabilities.mEnforcedAdmin = enforcedAdmin;
+        mUserCapabilities.mCanAddUser = false;
+        mUserCapabilities.mDisallowAddUser = true;
+        mUserCapabilities.mDisallowAddUserSetByAdmin = true;
+        doReturn(true).when(mAddUserPreference).isEnabled();
+
+        mFragment.updateUserList();
+
+        verify(mAddUserPreference).setVisible(true);
+        ArgumentCaptor<RestrictedLockUtils.EnforcedAdmin> captor = ArgumentCaptor.forClass(
+                RestrictedLockUtils.EnforcedAdmin.class);
+        verify(mAddUserPreference).setDisabledByAdmin(captor.capture());
+        assertThat(captor.getValue()).isEqualTo(enforcedAdmin);
+    }
+
+    @Test
+    public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() {
+        mUserCapabilities.mCanAddUser = false;
+
+        mFragment.updateUserList();
+
+        verify(mAddUserPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_canNotAddGuest_shouldNotShowAddGuest() {
+        mUserCapabilities.mCanAddGuest = false;
+
+        mFragment.updateUserList();
+
+        verify(mAddGuestPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_notProvisionedDevice_shouldNotShowAddUser() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0);
+        mUserCapabilities.mCanAddUser = true;
+
+        mFragment.updateUserList();
+
+        verify(mAddUserPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_notProvisionedDevice_shouldNotShowAddGuest() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0);
+        mUserCapabilities.mCanAddGuest = true;
+
+        mFragment.updateUserList();
+
+        verify(mAddGuestPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_userSwitcherDisabled_shouldNotShowAddUser() {
+        mUserCapabilities.mCanAddUser = true;
+        mUserCapabilities.mUserSwitcherEnabled = false;
+
+        mFragment.updateUserList();
+
+        verify(mAddUserPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_userSwitcherDisabled_shouldNotShowAddGuest() {
+        mUserCapabilities.mCanAddGuest = true;
+        mUserCapabilities.mUserSwitcherEnabled = false;
+
+        mFragment.updateUserList();
+
+        verify(mAddGuestPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_shouldAddAdminUserPreference() {
+        givenUsers(getAdminUser(true));
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory).addPreference(captor.capture());
+        UserPreference adminPref = captor.getValue();
+        assertThat(adminPref).isSameAs(mMePreference);
+    }
+
+    @Test
+    public void updateUserList_existingGuest_shouldAddGuestUserPreference() {
+        givenUsers(getAdminUser(true), getGuest(false));
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory, times(2))
+                .addPreference(captor.capture());
+        UserPreference guestPref = captor.getAllValues().get(1);
+        assertThat(guestPref.getUserId()).isEqualTo(INACTIVE_GUEST_USER_ID);
+        assertThat(guestPref.getTitle()).isEqualTo("Guest");
+        assertThat(guestPref.getIcon()).isNotNull();
+        assertThat(guestPref.getKey()).isEqualTo(KEY_USER_GUEST);
+        assertThat(guestPref.isEnabled()).isEqualTo(true);
+        assertThat(guestPref.isSelectable()).isEqualTo(true);
+        assertThat(guestPref.getOnPreferenceClickListener()).isSameAs(mFragment);
+    }
+
+    @Test
+    public void updateUserList_existingSecondaryUser_shouldAddSecondaryUserPreference() {
+        givenUsers(getAdminUser(true), getSecondaryUser(false));
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory, times(2))
+                .addPreference(captor.capture());
+        UserPreference userPref = captor.getAllValues().get(1);
+        assertThat(userPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
+        assertThat(userPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
+        assertThat(userPref.getIcon()).isNotNull();
+        assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
+        assertThat(userPref.isEnabled()).isEqualTo(true);
+        assertThat(userPref.isSelectable()).isEqualTo(true);
+        assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
+    }
+
+    @Test
+    public void updateUserList_existingRestrictedUser_shouldAddRestrictedUserPreference() {
+        givenUsers(getAdminUser(true), getRestrictedUser(false));
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory, times(2))
+                .addPreference(captor.capture());
+        UserPreference userPref = captor.getAllValues().get(1);
+        assertThat(userPref.getUserId()).isEqualTo(INACTIVE_RESTRICTED_USER_ID);
+        assertThat(userPref.getTitle()).isEqualTo(RESTRICTED_USER_NAME);
+        assertThat(userPref.getIcon()).isNotNull();
+        assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_RESTRICTED_USER_ID);
+        assertThat(userPref.getSummary()).isEqualTo("Restricted profile");
+        assertThat(userPref.isEnabled()).isEqualTo(true);
+        assertThat(userPref.isSelectable()).isEqualTo(true);
+        assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
+    }
+
+    @Test
+    public void updateUserList_existingManagedUser_shouldNotAddUserPreference() {
+        givenUsers(getAdminUser(true), getManagedUser());
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory).addPreference(captor.capture());
+        List<UserPreference> userPreferences = captor.getAllValues();
+        assertThat(userPreferences.size()).isEqualTo(1);
+        assertThat(userPreferences.get(0).getUserId()).isEqualTo(ACTIVE_USER_ID);
+    }
+
+    @Test
+    public void updateUserList_uninitializedRestrictedUser_shouldAddUserPreference() {
+        UserInfo restrictedUser = getRestrictedUser(false);
+        removeFlag(restrictedUser, UserInfo.FLAG_INITIALIZED);
+        givenUsers(getAdminUser(true), restrictedUser);
+        doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
+        mUserCapabilities.mDisallowSwitchUser = false;
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory, times(2))
+                .addPreference(captor.capture());
+        UserPreference userPref = captor.getAllValues().get(1);
+        assertThat(userPref.getUserId()).isEqualTo(INACTIVE_RESTRICTED_USER_ID);
+        assertThat(userPref.getTitle()).isEqualTo(RESTRICTED_USER_NAME);
+        assertThat(userPref.getIcon()).isNotNull();
+        assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_RESTRICTED_USER_ID);
+        assertThat(userPref.getSummary()).isEqualTo("Not set up - Restricted profile");
+        assertThat(userPref.isEnabled()).isEqualTo(true);
+        assertThat(userPref.isSelectable()).isEqualTo(true);
+        assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
+    }
+
+    @Test
+    public void updateUserList_uninitializedUserAndCanNotSwitchUser_shouldDisablePref() {
+        UserInfo uninitializedUser = getSecondaryUser(false);
+        removeFlag(uninitializedUser, UserInfo.FLAG_INITIALIZED);
+        givenUsers(getAdminUser(true), uninitializedUser);
+        doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED)
+                .when(mUserManager).getUserSwitchability();
+        mUserCapabilities.mDisallowSwitchUser = false;
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory, times(2))
+                .addPreference(captor.capture());
+        UserPreference userPref = captor.getAllValues().get(1);
+        assertThat(userPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
+        assertThat(userPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
+        assertThat(userPref.getIcon()).isNotNull();
+        assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
+        assertThat(userPref.getSummary()).isEqualTo("Not set up");
+        assertThat(userPref.isEnabled()).isEqualTo(false);
+        assertThat(userPref.isSelectable()).isEqualTo(true);
+        assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
+    }
+
+    @Test
+    public void updateUserList_guestWithoutInitializedFlag_shouldNotSetSummary() {
+        UserInfo guest = getGuest(false);
+        removeFlag(guest, UserInfo.FLAG_INITIALIZED);
+        givenUsers(getAdminUser(true), guest);
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory, times(2))
+                .addPreference(captor.capture());
+        UserPreference userPref = captor.getAllValues().get(1);
+        assertThat(userPref.getUserId()).isEqualTo(INACTIVE_GUEST_USER_ID);
+        assertThat(userPref.getSummary()).isNull();
+    }
+
+    @Test
+    public void updateUserList_activeUserWithoutInitializedFlag_shouldNotSetSummary() {
+        UserInfo activeUser = getSecondaryUser(true);
+        removeFlag(activeUser, UserInfo.FLAG_INITIALIZED);
+        givenUsers(activeUser);
+
+        mFragment.updateUserList();
+
+        ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
+        verify(mFragment.mUserListCategory).addPreference(captor.capture());
+        UserPreference userPref = captor.getValue();
+        assertThat(userPref.getUserId()).isEqualTo(ACTIVE_USER_ID);
+        assertThat(userPref.getSummary()).isNull();
+    }
+
+    @Test
+    public void updateUserList_guestIsAlreadyCreated_shouldNotShowAddGuest() {
+        givenUsers(getAdminUser(true), getGuest(true));
+        mUserCapabilities.mCanAddGuest = true;
+
+        mFragment.updateUserList();
+
+        verify(mAddGuestPreference).setVisible(false);
+    }
+
+    @Test
+    public void updateUserList_userIconLoaded_shouldNotLoadIcon() {
+        UserInfo currentUser = getAdminUser(true);
+        currentUser.iconPath = "/data/system/users/0/photo.png";
+        givenUsers(currentUser);
+        mFragment.mUserIcons.put(ACTIVE_USER_ID,
+                Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888));
+
+        mFragment.updateUserList();
+
+        verify(mUserManager, never()).getUserIcon(anyInt());
+        // updateUserList should be called only once
+        verify(mUserManager).getUsers(true);
+    }
+
+    @Test
+    public void updateUserList_userIconMissing_shouldLoadIcon() {
+        UserInfo currentUser = getAdminUser(true);
+        currentUser.iconPath = "/data/system/users/0/photo.png";
+        givenUsers(currentUser);
+        // create a non-empty sparsearray
+        mFragment.mUserIcons.put(5, Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888));
+        Bitmap userIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
+        doReturn(userIcon).when(mUserManager).getUserIcon(ACTIVE_USER_ID);
+
+        mFragment.updateUserList();
+
+        verify(mUserManager).getUserIcon(ACTIVE_USER_ID);
+        // updateUserList should be called another time after loading the icons
+        verify(mUserManager, times(2)).getUsers(true);
+    }
+
+    @Test
+    public void getRealUsersCount_onlyAdmin_shouldCount() {
+        givenUsers(getAdminUser(true));
+
+        int result = mFragment.getRealUsersCount();
+
+        assertThat(result).isEqualTo(1);
+        verify(mUserManager).getUsers();
+    }
+
+    @Test
+    public void getRealUsersCount_secondaryUser_shouldCount() {
+        givenUsers(getAdminUser(true), getSecondaryUser(false));
+
+        int result = mFragment.getRealUsersCount();
+
+        assertThat(result).isEqualTo(2);
+        verify(mUserManager).getUsers();
+    }
+
+    @Test
+    public void getRealUsersCount_restrictedUser_shouldCount() {
+        givenUsers(getAdminUser(true), getSecondaryUser(false));
+
+        int result = mFragment.getRealUsersCount();
+
+        assertThat(result).isEqualTo(2);
+        verify(mUserManager).getUsers();
+    }
+
+    @Test
+    public void getRealUsersCount_guest_shouldNotCount() {
+        givenUsers(getAdminUser(true), getGuest(false));
+
+        int result = mFragment.getRealUsersCount();
+
+        assertThat(result).isEqualTo(1);
+        verify(mUserManager).getUsers();
+    }
+
+    @Test
+    public void getRealUsersCount_managedUser_shouldNotCount() {
+        givenUsers(getAdminUser(true), getManagedUser());
+
+        int result = mFragment.getRealUsersCount();
+
+        assertThat(result).isEqualTo(1);
+        verify(mUserManager).getUsers();
+    }
+
+    private void givenUsers(UserInfo... userInfo) {
+        List<UserInfo> users = Arrays.asList(userInfo);
+        doReturn(users).when(mUserManager).getUsers();
+        doReturn(users).when(mUserManager).getUsers(anyBoolean());
+    }
+
+    private static void removeFlag(UserInfo userInfo, int flag) {
+        userInfo.flags &= ~flag;
+    }
+
+    private static UserInfo getAdminUser(boolean active) {
+        return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_ADMIN_USER_ID, ADMIN_USER_NAME,
+                null,
+                UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN,
+                UserManager.USER_TYPE_FULL_SYSTEM);
+    }
+
+    private static UserInfo getSecondaryUser(boolean active) {
+        return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_SECONDARY_USER_ID,
+                SECONDARY_USER_NAME, null,
+                UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED,
+                UserManager.USER_TYPE_FULL_SECONDARY);
+    }
+
+    private static UserInfo getRestrictedUser(boolean active) {
+        return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_RESTRICTED_USER_ID,
+                RESTRICTED_USER_NAME, null,
+                UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_RESTRICTED,
+                UserManager.USER_TYPE_FULL_RESTRICTED);
+    }
+
+    private static UserInfo getManagedUser() {
+        return new UserInfo(MANAGED_USER_ID,
+                MANAGED_USER_NAME, null,
+                UserInfo.FLAG_PROFILE | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE,
+                UserManager.USER_TYPE_PROFILE_MANAGED);
+    }
+
+    private static UserInfo getGuest(boolean active) {
+        return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_GUEST_USER_ID, GUEST_USER_NAME,
+                null,
+                UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_GUEST,
+                UserManager.USER_TYPE_FULL_GUEST);
+    }
+
+
 }