diff --git a/packages/SystemUI/res/drawable/ic_add_supervised_user.xml b/packages/SystemUI/res/drawable/ic_add_supervised_user.xml
new file mode 100644
index 0000000000000..627743ed16697
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_add_supervised_user.xml
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d39e295689864..3e9e00129bf72 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2402,4 +2402,6 @@
Add
+
+ @*android:string/supervised_user_creation_label
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 3ece240bc5766..f1093d18a28b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -46,6 +46,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.TelephonyCallback;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -159,6 +160,7 @@ public class UserSwitcherController implements Dumpable {
private final AtomicBoolean mGuestCreationScheduled;
private FalsingManager mFalsingManager;
private View mView;
+ private String mCreateSupervisedUserPackage;
@Inject
public UserSwitcherController(Context context,
@@ -255,6 +257,9 @@ public class UserSwitcherController implements Dumpable {
keyguardStateController.addCallback(mCallback);
listenForCallState();
+ mCreateSupervisedUserPackage = mContext.getString(
+ com.android.internal.R.string.config_supervisedUserCreationPackage);
+
dumpManager.registerDumpable(getClass().getSimpleName(), this);
refreshUsers(UserHandle.USER_NULL);
@@ -307,14 +312,10 @@ public class UserSwitcherController implements Dumpable {
// User 0
boolean canSwitchUsers = mUserManager.getUserSwitchability(
UserHandle.of(mUserTracker.getUserId())) == SWITCHABILITY_STATUS_OK;
- UserInfo currentUserInfo = null;
UserRecord guestRecord = null;
for (UserInfo info : infos) {
boolean isCurrent = currentId == info.id;
- if (isCurrent) {
- currentUserInfo = info;
- }
boolean switchToEnabled = canSwitchUsers || isCurrent;
if (info.isEnabled()) {
if (info.isGuest()) {
@@ -322,7 +323,8 @@ public class UserSwitcherController implements Dumpable {
// the icon shouldn't be enabled even if the user is current
guestRecord = new UserRecord(info, null /* picture */,
true /* isGuest */, isCurrent, false /* isAddUser */,
- false /* isRestricted */, canSwitchUsers);
+ false /* isRestricted */, canSwitchUsers,
+ false /* isAddSupervisedUser */);
} else if (info.supportsSwitchToByUser()) {
Bitmap picture = bitmaps.get(info.id);
if (picture == null) {
@@ -337,7 +339,7 @@ public class UserSwitcherController implements Dumpable {
}
records.add(new UserRecord(info, picture, false /* isGuest */,
isCurrent, false /* isAddUser */, false /* isRestricted */,
- switchToEnabled));
+ switchToEnabled, false /* isAddSupervisedUser */));
}
}
}
@@ -345,19 +347,6 @@ public class UserSwitcherController implements Dumpable {
Prefs.putBoolean(mContext, Key.SEEN_MULTI_USER, true);
}
- boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
- UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
- boolean currentUserCanCreateUsers = currentUserInfo != null
- && (currentUserInfo.isAdmin()
- || currentUserInfo.id == UserHandle.USER_SYSTEM)
- && systemCanCreateUsers;
- boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
- boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
- && guestRecord == null;
- boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
- && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY);
- boolean createIsRestricted = !addUsersWhenLocked;
-
if (guestRecord == null) {
if (mGuestUserAutoCreated) {
// If mGuestIsResetting=true, the switch should be disabled since
@@ -368,13 +357,14 @@ public class UserSwitcherController implements Dumpable {
guestRecord = new UserRecord(null /* info */, null /* picture */,
true /* isGuest */, false /* isCurrent */,
false /* isAddUser */, false /* isRestricted */,
- isSwitchToGuestEnabled);
+ isSwitchToGuestEnabled, false /* isAddSupervisedUser */);
checkIfAddUserDisallowedByAdminOnly(guestRecord);
records.add(guestRecord);
- } else if (canCreateGuest) {
+ } else if (canCreateGuest(guestRecord != null)) {
guestRecord = new UserRecord(null /* info */, null /* picture */,
true /* isGuest */, false /* isCurrent */,
- false /* isAddUser */, createIsRestricted, canSwitchUsers);
+ false /* isAddUser */, createIsRestricted(), canSwitchUsers,
+ false /* isAddSupervisedUser */);
checkIfAddUserDisallowedByAdminOnly(guestRecord);
records.add(guestRecord);
}
@@ -382,10 +372,19 @@ public class UserSwitcherController implements Dumpable {
records.add(guestRecord);
}
- if (canCreateUser) {
+ if (canCreateUser()) {
UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
- createIsRestricted, canSwitchUsers);
+ createIsRestricted(), canSwitchUsers,
+ false /* isAddSupervisedUser */);
+ checkIfAddUserDisallowedByAdminOnly(addUserRecord);
+ records.add(addUserRecord);
+ }
+
+ if (canCreateSupervisedUser()) {
+ UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
+ false /* isGuest */, false /* isCurrent */, false /* isAddUser */,
+ createIsRestricted(), canSwitchUsers, true /* isAddSupervisedUser */);
checkIfAddUserDisallowedByAdminOnly(addUserRecord);
records.add(addUserRecord);
}
@@ -403,6 +402,40 @@ public class UserSwitcherController implements Dumpable {
}.execute((SparseArray) bitmaps);
}
+ boolean systemCanCreateUsers() {
+ return !mUserManager.hasBaseUserRestriction(
+ UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
+ }
+
+ boolean currentUserCanCreateUsers() {
+ UserInfo currentUser = mUserTracker.getUserInfo();
+ return currentUser != null
+ && (currentUser.isAdmin() || mUserTracker.getUserId() == UserHandle.USER_SYSTEM)
+ && systemCanCreateUsers();
+ }
+
+ boolean anyoneCanCreateUsers() {
+ return systemCanCreateUsers() && mAddUsersFromLockScreen;
+ }
+
+ boolean canCreateGuest(boolean hasExistingGuest) {
+ return (currentUserCanCreateUsers() || anyoneCanCreateUsers())
+ && !hasExistingGuest;
+ }
+
+ boolean canCreateUser() {
+ return (currentUserCanCreateUsers() || anyoneCanCreateUsers())
+ && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY);
+ }
+
+ boolean createIsRestricted() {
+ return mAddUsersFromLockScreen;
+ }
+
+ boolean canCreateSupervisedUser() {
+ return !TextUtils.isEmpty(mCreateSupervisedUserPackage) && canCreateUser();
+ }
+
private void pauseRefreshUsers() {
if (!mPauseRefreshUsers) {
mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
@@ -485,6 +518,9 @@ public class UserSwitcherController implements Dumpable {
} else if (record.isAddUser) {
showAddUserDialog(dialogShower);
return;
+ } else if (record.isAddSupervisedUser) {
+ startSupervisedUserActivity();
+ return;
} else {
id = record.info.id;
}
@@ -561,6 +597,22 @@ public class UserSwitcherController implements Dumpable {
}
}
+ private void startSupervisedUserActivity() {
+ final Intent intent = new Intent()
+ .setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
+ .setPackage(mCreateSupervisedUserPackage)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // TODO(b/209659998): [to-be-removed] fallback activity for supervised user creation.
+ if (mContext.getPackageManager().resolveActivity(intent, 0) == null) {
+ intent.setPackage(null)
+ .setClassName("com.android.settings",
+ "com.android.settings.users.AddSupervisedUserActivity");
+ }
+
+ mContext.startActivity(intent);
+ }
+
private void listenForCallState() {
mTelephonyListenerManager.addCallStateListener(mPhoneStateListener);
}
@@ -941,6 +993,8 @@ public class UserSwitcherController implements Dumpable {
}
} else if (item.isAddUser) {
return context.getString(R.string.user_add_user);
+ } else if (item.isAddSupervisedUser) {
+ return context.getString(R.string.add_user_supervised);
} else {
return item.info.name;
}
@@ -958,6 +1012,8 @@ public class UserSwitcherController implements Dumpable {
iconRes = R.drawable.ic_add_circle;
} else if (item.isGuest) {
iconRes = R.drawable.ic_avatar_guest_user;
+ } else if (item.isAddSupervisedUser) {
+ iconRes = R.drawable.ic_add_supervised_user;
} else {
iconRes = R.drawable.ic_avatar_user;
}
@@ -1000,6 +1056,7 @@ public class UserSwitcherController implements Dumpable {
public final boolean isGuest;
public final boolean isCurrent;
public final boolean isAddUser;
+ public final boolean isAddSupervisedUser;
/** If true, the record is only visible to the owner and only when unlocked. */
public final boolean isRestricted;
public boolean isDisabledByAdmin;
@@ -1007,7 +1064,8 @@ public class UserSwitcherController implements Dumpable {
public boolean isSwitchToEnabled;
public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
- boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
+ boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled,
+ boolean isAddSupervisedUser) {
this.info = info;
this.picture = picture;
this.isGuest = isGuest;
@@ -1015,11 +1073,12 @@ public class UserSwitcherController implements Dumpable {
this.isAddUser = isAddUser;
this.isRestricted = isRestricted;
this.isSwitchToEnabled = isSwitchToEnabled;
+ this.isAddSupervisedUser = isAddSupervisedUser;
}
public UserRecord copyWithIsCurrent(boolean _isCurrent) {
return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
- isSwitchToEnabled);
+ isSwitchToEnabled, isAddSupervisedUser);
}
public int resolveId() {
@@ -1043,6 +1102,7 @@ public class UserSwitcherController implements Dumpable {
}
if (isGuest) sb.append(" ");
if (isAddUser) sb.append(" ");
+ if (isAddSupervisedUser) sb.append(" ");
if (isCurrent) sb.append(" ");
if (picture != null) sb.append(" ");
if (isRestricted) sb.append(" ");
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
index d6a8ab270b845..02e71897500f5 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
@@ -71,8 +71,7 @@ class UserSwitcherActivity @Inject constructor(
private lateinit var broadcastReceiver: BroadcastReceiver
private var popupMenu: UserSwitcherPopupMenu? = null
private lateinit var addButton: View
- private var addUserItem: UserRecord? = null
- private var addGuestItem: UserRecord? = null
+ private var addUserRecords = mutableListOf()
private val adapter = object : BaseUserAdapter(userSwitcherController) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
@@ -203,8 +202,7 @@ class UserSwitcherActivity @Inject constructor(
private fun showPopupMenu() {
val items = mutableListOf()
- addUserItem?.let { items.add(it) }
- addGuestItem?.let { items.add(it) }
+ addUserRecords.forEach { items.add(it) }
var popupMenuAdapter = ItemAdapter(
this,
@@ -249,10 +247,10 @@ class UserSwitcherActivity @Inject constructor(
val flow = requireViewById(R.id.flow)
for (i in 0 until adapter.getCount()) {
val item = adapter.getItem(i)
- if (item.isAddUser) {
- addUserItem = item
- } else if (item.isGuest && item.info == null) {
- addGuestItem = item
+ if (item.isAddUser ||
+ item.isAddSupervisedUser ||
+ item.isGuest && item.info == null) {
+ addUserRecords.add(item)
} else {
val userView = adapter.getView(i, null, parent)
userView.setId(View.generateViewId())
@@ -273,7 +271,7 @@ class UserSwitcherActivity @Inject constructor(
}
}
- if (addUserItem != null || addGuestItem != null) {
+ if (!addUserRecords.isEmpty()) {
addButton.visibility = View.VISIBLE
} else {
addButton.visibility = View.GONE
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 24b01e079b428..6736bfd217404 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -307,7 +307,8 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
UserInfo info = new UserInfo(i /* id */, "Name: " + i, null /* iconPath */,
0 /* flags */);
users.add(new UserRecord(info, null, false /* isGuest */, false /* isCurrent */,
- false /* isAddUser */, false /* isRestricted */, true /* isSwitchToEnabled */));
+ false /* isAddUser */, false /* isRestricted */, true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */));
}
return users;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
index 3a3d1546984d1..9b0142d6a8fe4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -147,5 +147,6 @@ class UserDetailViewAdapterTest : SysuiTestCase() {
current,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
index e479882ac50a8..0dd6cbb7995ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
@@ -193,5 +193,6 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
isCurrentUser,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index 9a7e702152b49..9dabf6907f7cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -56,6 +56,7 @@ import com.android.systemui.util.time.FakeSystemClock
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -130,6 +131,21 @@ class UserSwitcherControllerTest : SysuiTestCase() {
.thenReturn(true)
`when`(notificationShadeWindowView.context).thenReturn(context)
+ // Since userSwitcherController involves InteractionJankMonitor.
+ // Let's fulfill the dependencies.
+ val mockedContext = mock(Context::class.java)
+ doReturn(mockedContext).`when`(notificationShadeWindowView).context
+ doReturn(true).`when`(notificationShadeWindowView).isAttachedToWindow
+ doNothing().`when`(threadedRenderer).addObserver(any())
+ doNothing().`when`(threadedRenderer).removeObserver(any())
+ doReturn(threadedRenderer).`when`(notificationShadeWindowView).threadedRenderer
+
+ picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user))
+
+ setupController()
+ }
+
+ private fun setupController() {
userSwitcherController = UserSwitcherController(
context,
activityManager,
@@ -153,18 +169,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
dumpManager,
dialogLaunchAnimator)
userSwitcherController.mPauseRefreshUsers = true
-
- // Since userSwitcherController involves InteractionJankMonitor.
- // Let's fulfill the dependencies.
- val mockedContext = mock(Context::class.java)
- doReturn(mockedContext).`when`(notificationShadeWindowView).context
- doReturn(true).`when`(notificationShadeWindowView).isAttachedToWindow
- doNothing().`when`(threadedRenderer).addObserver(any())
- doNothing().`when`(threadedRenderer).removeObserver(any())
- doReturn(threadedRenderer).`when`(notificationShadeWindowView).threadedRenderer
- userSwitcherController.init(notificationShadeWindowView)
-
- picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user))
userSwitcherController.init(notificationShadeWindowView)
}
@@ -177,7 +181,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -196,7 +201,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -220,7 +226,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -240,7 +247,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
true /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -262,7 +270,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
true /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -283,7 +292,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
true /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -302,7 +312,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
true /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -323,7 +334,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -357,7 +369,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* current */,
false /* isAddUser */,
false /* isRestricted */,
- true /* isSwitchToEnabled */)
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */)
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -389,7 +402,7 @@ class UserSwitcherControllerTest : SysuiTestCase() {
userSwitcherController.users.add(UserSwitcherController.UserRecord(
UserInfo(id, name, 0),
null, false, isCurrent, false,
- false, false
+ false, false, false
))
}
val bgUserName = "background_user"
@@ -412,4 +425,42 @@ class UserSwitcherControllerTest : SysuiTestCase() {
`when`(userTracker.userId).thenReturn(1)
assertEquals(false, userSwitcherController.isSystemUser)
}
+
+ @Test
+ fun testCanCreateSupervisedUserWithConfiguredPackage() {
+ // GIVEN the supervised user creation package is configured
+ `when`(context.getString(
+ com.android.internal.R.string.config_supervisedUserCreationPackage))
+ .thenReturn("some_pkg")
+
+ // AND the current user is allowed to create new users
+ `when`(userTracker.userId).thenReturn(ownerId)
+ `when`(userTracker.userInfo).thenReturn(ownerInfo)
+
+ // WHEN the controller is started with the above config
+ setupController()
+ testableLooper.processAllMessages()
+
+ // THEN a supervised user can be constructed
+ assertTrue(userSwitcherController.canCreateSupervisedUser())
+ }
+
+ @Test
+ fun testCannotCreateSupervisedUserWithConfiguredPackage() {
+ // GIVEN the supervised user creation package is NOT configured
+ `when`(context.getString(
+ com.android.internal.R.string.config_supervisedUserCreationPackage))
+ .thenReturn(null)
+
+ // AND the current user is allowed to create new users
+ `when`(userTracker.userId).thenReturn(ownerId)
+ `when`(userTracker.userInfo).thenReturn(ownerInfo)
+
+ // WHEN the controller is started with the above config
+ setupController()
+ testableLooper.processAllMessages()
+
+ // THEN a supervised user can NOT be constructed
+ assertFalse(userSwitcherController.canCreateSupervisedUser())
+ }
}