Enforce disallow switch user in user settings

Disallow the following actions which result in switch user when DISALLOW_USER_SWITCH is set
- Creating guest
- Showing user setup dialog for newly created user
- Clicking uninitialized user preference

Bug: 71694430
Test: CTSVerifier DeviceOwnerPositiveTest - DISALLOW_USER_SWITCH
Test: m -j ROBOTEST_FILTER=UserCapabilitiesTest RunSettingsRoboTests
Test: m -j ROBOTEST_FILTER=AddUserWhenLockedPreferenceController RunSettingsRoboTests
Test: m -j ROBOTEST_FILTER=UserSettingsTest RunSettingsRoboTests
Change-Id: Ia4c7e7b4947bfaf2ebeef4d32a473bdac542d6a6
diff --git a/src/com/android/settings/users/UserCapabilities.java b/src/com/android/settings/users/UserCapabilities.java
index 084a5db..f1bfae9 100644
--- a/src/com/android/settings/users/UserCapabilities.java
+++ b/src/com/android/settings/users/UserCapabilities.java
@@ -34,6 +34,7 @@
     boolean mCanAddGuest;
     boolean mDisallowAddUser;
     boolean mDisallowAddUserSetByAdmin;
+    boolean mDisallowSwitchUser;
     RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
 
     private UserCapabilities() {}
@@ -79,6 +80,9 @@
         final boolean canAddUsersWhenLocked = mIsAdmin || Settings.Global.getInt(
                 context.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1;
         mCanAddGuest = !mIsGuest && !mDisallowAddUser && canAddUsersWhenLocked;
+
+        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mDisallowSwitchUser = userManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
     }
 
     public boolean isAdmin() {
@@ -109,6 +113,7 @@
                 ", mCanAddGuest=" + mCanAddGuest +
                 ", mDisallowAddUser=" + mDisallowAddUser +
                 ", mEnforcedAdmin=" + mEnforcedAdmin +
+                ", mDisallowSwitchUser=" + mDisallowSwitchUser +
                 '}';
     }
 }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index a8fab13..3520a59 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -754,8 +754,12 @@
                     synchronized (mUserLock) {
                         if (userType == USER_TYPE_USER) {
                             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
-                            mHandler.sendMessage(mHandler.obtainMessage(
-                                    MESSAGE_SETUP_USER, user.id, user.serialNumber));
+                            // Skip setting up user which results in user switching when the
+                            // restriction is set.
+                            if (!mUserCaps.mDisallowSwitchUser) {
+                                mHandler.sendMessage(mHandler.obtainMessage(
+                                        MESSAGE_SETUP_USER, user.id, user.serialNumber));
+                            }
                         } else {
                             mHandler.sendMessage(mHandler.obtainMessage(
                                     MESSAGE_CONFIG_USER, user.id, user.serialNumber));
@@ -842,8 +846,12 @@
                 } else {
                     pref.setSummary(R.string.user_summary_not_set_up);
                 }
-                pref.setOnPreferenceClickListener(this);
-                pref.setSelectable(true);
+                // Disallow setting up user which results in user switching when the restriction is
+                // set.
+                if (!mUserCaps.mDisallowSwitchUser) {
+                    pref.setOnPreferenceClickListener(this);
+                    pref.setSelectable(true);
+                }
             } else if (user.isRestricted()) {
                 pref.setSummary(R.string.user_summary_restricted_profile);
             }
@@ -882,8 +890,13 @@
             pref.setTitle(R.string.user_guest);
             pref.setIcon(getEncircledDefaultIcon());
             userPreferences.add(pref);
-            pref.setDisabledByAdmin(
-                    mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
+            if (mUserCaps.mDisallowAddUser) {
+                pref.setDisabledByAdmin(mUserCaps.mEnforcedAdmin);
+            } else if (mUserCaps.mDisallowSwitchUser) {
+                pref.setDisabledByAdmin(RestrictedLockUtils.getDeviceOwner(context));
+            } else {
+                pref.setDisabledByAdmin(null);
+            }
             int finalGuestId = guestId;
             pref.setOnPreferenceClickListener(preference -> {
                 int id = finalGuestId;
diff --git a/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
new file mode 100644
index 0000000..4228ca0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/users/UserCapabilitiesTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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 com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UserCapabilitiesTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private UserManager mUserManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+    }
+
+    @Test
+    public void disallowUserSwitchWhenRestrictionIsSet() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
+
+        UserCapabilities userCapabilities = UserCapabilities.create(mContext);
+        userCapabilities.updateAddUserCapabilities(mContext);
+
+        assertThat(userCapabilities.mDisallowSwitchUser).isTrue();
+    }
+
+    @Test
+    public void allowUserSwitchWhenRestrictionIsNotSet() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
+
+        UserCapabilities userCapabilities = UserCapabilities.create(mContext);
+        userCapabilities.updateAddUserCapabilities(mContext);
+
+        assertThat(userCapabilities.mDisallowSwitchUser).isFalse();
+    }
+}