summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/multiuser.aconfig8
-rw-r--r--core/java/android/os/IUserManager.aidl1
-rw-r--r--core/java/android/os/UserManager.java47
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java33
-rw-r--r--services/core/java/com/android/server/pm/UserTypeFactory.java1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java108
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java18
7 files changed, 207 insertions, 9 deletions
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index ac80561c3b50..48a7cc920f1d 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -184,3 +184,11 @@ flag {
description: "Enable Private Space telephony and SMS intent redirection to the main user"
bug: "325576602"
}
+
+flag {
+ name: "block_private_space_creation"
+ namespace: "profile_experiences"
+ description: "Allow blocking private space creation based on specific conditions"
+ bug: "290333800"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 800ba6d3a542..23d6007e3d8b 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -85,6 +85,7 @@ interface IUserManager {
boolean isUserSwitcherEnabled(boolean showEvenIfNotActionable, int mUserId);
boolean isRestricted(int userId);
boolean canHaveRestrictedProfile(int userId);
+ boolean canAddPrivateProfile(int userId);
int getUserSerialNumber(int userId);
int getUserHandle(int userSerialNumber);
int getUserRestrictionSource(String restrictionKey, int userId);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9757a1096a30..fdaa0b467566 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2353,6 +2353,17 @@ public class UserManager {
public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7;
/**
+ * Indicates user operation failed because user is disabled on the device.
+ * @hide
+ */
+ public static final int USER_OPERATION_ERROR_DISABLED_USER = 8;
+ /**
+ * Indicates user operation failed because user is disabled on the device.
+ * @hide
+ */
+ public static final int USER_OPERATION_ERROR_PRIVATE_PROFILE = 9;
+
+ /**
* Result returned from various user operations.
*
* @hide
@@ -2366,7 +2377,9 @@ public class UserManager {
USER_OPERATION_ERROR_CURRENT_USER,
USER_OPERATION_ERROR_LOW_STORAGE,
USER_OPERATION_ERROR_MAX_USERS,
- USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS
+ USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS,
+ USER_OPERATION_ERROR_DISABLED_USER,
+ USER_OPERATION_ERROR_PRIVATE_PROFILE,
})
public @interface UserOperationResult {}
@@ -2563,6 +2576,17 @@ public class UserManager {
}
/**
+ * Returns whether the device supports Private Profile
+ * @hide
+ */
+ public static boolean isPrivateProfileEnabled() {
+ if (android.multiuser.Flags.blockPrivateSpaceCreation()) {
+ return !ActivityManager.isLowRamDeviceStatic();
+ }
+ return true;
+ }
+
+ /**
* Returns whether multiple admins are enabled on the device
* @hide
*/
@@ -3155,6 +3179,27 @@ public class UserManager {
}
/**
+ * Checks if it's possible to add a private profile to the context user
+ * @return whether the context user can add a private profile.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS},
+ conditional = true)
+ @UserHandleAware
+ public boolean canAddPrivateProfile() {
+ if (android.multiuser.Flags.blockPrivateSpaceCreation()) {
+ try {
+ return mService.canAddPrivateProfile(mUserId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return true;
+ }
+
+ /**
* Returns whether the context user has at least one restricted profile associated with it.
* @return whether the user has a restricted profile associated with it
* @hide
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7349755402b1..e0af5fcab779 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -21,10 +21,15 @@ import static android.content.Intent.ACTION_SCREEN_ON;
import static android.content.Intent.EXTRA_USER_ID;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_EMBEDDED;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.os.UserManager.DEV_CREATE_OVERRIDE_PROPERTY;
import static android.os.UserManager.DISALLOW_USER_SWITCH;
import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY;
import static android.os.UserManager.USER_OPERATION_ERROR_UNKNOWN;
+import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
import static com.android.internal.app.SetScreenLockDialogActivity.EXTRA_ORIGIN_USER_ID;
import static com.android.internal.app.SetScreenLockDialogActivity.LAUNCH_REASON_DISABLE_QUIET_MODE;
@@ -1006,6 +1011,13 @@ public class UserManagerService extends IUserManager.Stub {
emulateSystemUserModeIfNeeded();
}
+ private boolean doesDeviceHardwareSupportPrivateSpace() {
+ return !mPm.hasSystemFeature(FEATURE_EMBEDDED, 0)
+ && !mPm.hasSystemFeature(FEATURE_WATCH, 0)
+ && !mPm.hasSystemFeature(FEATURE_LEANBACK, 0)
+ && !mPm.hasSystemFeature(FEATURE_AUTOMOTIVE, 0);
+ }
+
private static boolean isAutoLockForPrivateSpaceEnabled() {
return android.os.Flags.allowPrivateProfile()
&& Flags.supportAutolockForPrivateSpace();
@@ -2751,6 +2763,18 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public boolean canAddPrivateProfile(@UserIdInt int userId) {
+ checkCreateUsersPermission("canHaveRestrictedProfile");
+ UserInfo parentUserInfo = getUserInfo(userId);
+ return isUserTypeEnabled(USER_TYPE_PROFILE_PRIVATE)
+ && canAddMoreProfilesToUser(USER_TYPE_PROFILE_PRIVATE,
+ userId, /* allowedToRemoveOne */ false)
+ && (parentUserInfo != null && parentUserInfo.isMain())
+ && doesDeviceHardwareSupportPrivateSpace()
+ && !hasUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, userId);
+ }
+
+ @Override
public boolean hasRestrictedProfiles(@UserIdInt int userId) {
checkManageUsersPermission("hasRestrictedProfiles");
synchronized (mUsersLock) {
@@ -5308,7 +5332,7 @@ public class UserManagerService extends IUserManager.Stub {
if (!isUserTypeEnabled(userTypeDetails)) {
throwCheckedUserOperationException(
"Cannot add a user of disabled type " + userType + ".",
- UserManager.USER_OPERATION_ERROR_MAX_USERS);
+ UserManager.USER_OPERATION_ERROR_DISABLED_USER);
}
synchronized (mUsersLock) {
@@ -5341,6 +5365,7 @@ public class UserManagerService extends IUserManager.Stub {
final boolean isDemo = UserManager.isUserTypeDemo(userType);
final boolean isManagedProfile = UserManager.isUserTypeManagedProfile(userType);
final boolean isCommunalProfile = UserManager.isUserTypeCommunalProfile(userType);
+ final boolean isPrivateProfile = UserManager.isUserTypePrivateProfile(userType);
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo;
@@ -5387,6 +5412,12 @@ public class UserManagerService extends IUserManager.Stub {
+ " for user " + parentId,
UserManager.USER_OPERATION_ERROR_MAX_USERS);
}
+ if (android.multiuser.Flags.blockPrivateSpaceCreation()
+ && isPrivateProfile && !canAddPrivateProfile(parentId)) {
+ throwCheckedUserOperationException(
+ "Cannot add profile of type " + userType + " for user " + parentId,
+ UserManager.USER_OPERATION_ERROR_PRIVATE_PROFILE);
+ }
if (isRestricted && (parentId != UserHandle.USER_SYSTEM)
&& !isCreationOverrideEnabled()) {
throwCheckedUserOperationException(
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 114daaac3c18..7f9c1cfafe68 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -292,6 +292,7 @@ public final class UserTypeFactory {
.setName(USER_TYPE_PROFILE_PRIVATE)
.setBaseType(FLAG_PROFILE)
.setMaxAllowedPerParent(1)
+ .setEnabled(UserManager.isPrivateProfileEnabled() ? 1 : 0)
.setLabels(R.string.profile_label_private)
.setIconBadge(com.android.internal.R.drawable.ic_private_profile_icon_badge)
.setBadgePlain(com.android.internal.R.drawable.ic_private_profile_badge)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 7bbcd50cdf1f..bc7c9a59ff29 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -15,6 +15,10 @@
*/
package com.android.server.pm;
+import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_EMBEDDED;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.os.UserManager.DISALLOW_OUTGOING_CALLS;
import static android.os.UserManager.DISALLOW_SMS;
import static android.os.UserManager.DISALLOW_USER_SWITCH;
@@ -41,6 +45,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.KeyguardManager;
import android.content.Context;
@@ -48,6 +53,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
import android.multiuser.Flags;
import android.os.PowerManager;
+import android.os.ServiceSpecificException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -76,6 +82,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -120,11 +127,14 @@ public final class UserManagerServiceTest {
private static final String TAG_RESTRICTIONS = "restrictions";
+ private static final String PRIVATE_PROFILE_NAME = "TestPrivateProfile";
+
@Rule
public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
.spyStatic(UserManager.class)
.spyStatic(LocalServices.class)
.spyStatic(SystemProperties.class)
+ .spyStatic(ActivityManager.class)
.mockStatic(Settings.Global.class)
.mockStatic(Settings.Secure.class)
.build();
@@ -163,6 +173,7 @@ public final class UserManagerServiceTest {
@Before
@UiThreadTest // Needed to initialize main handler
public void setFixtures() {
+ MockitoAnnotations.initMocks(this);
mSpiedContext = spy(mRealContext);
// Called when WatchedUserStates is constructed
@@ -172,11 +183,12 @@ public final class UserManagerServiceTest {
when(mDeviceStorageMonitorInternal.isMemoryLow()).thenReturn(false);
mockGetLocalService(DeviceStorageMonitorInternal.class, mDeviceStorageMonitorInternal);
when(mSpiedContext.getSystemService(StorageManager.class)).thenReturn(mStorageManager);
- when(mSpiedContext.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager);
+ doReturn(mKeyguardManager).when(mSpiedContext).getSystemService(KeyguardManager.class);
when(mSpiedContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
mockGetLocalService(LockSettingsInternal.class, mLockSettingsInternal);
mockGetLocalService(PackageManagerInternal.class, mPackageManagerInternal);
doNothing().when(mSpiedContext).sendBroadcastAsUser(any(), any(), any());
+ mockIsLowRamDevice(false);
// Must construct UserManagerService in the UiThread
mTestDir = new File(mRealContext.getDataDir(), "umstest");
@@ -570,9 +582,10 @@ public final class UserManagerServiceTest {
@Test
public void testAutoLockPrivateProfile() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
UserManagerService mSpiedUms = spy(mUms);
UserInfo privateProfileUser =
- mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
+ mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
Mockito.doNothing().when(mSpiedUms).setQuietModeEnabledAsync(
eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), any(),
@@ -587,10 +600,11 @@ public final class UserManagerServiceTest {
@Test
public void testAutoLockOnDeviceLockForPrivateProfile() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
UserManagerService mSpiedUms = spy(mUms);
UserInfo privateProfileUser =
- mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
+ mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK);
Mockito.doNothing().when(mSpiedUms).setQuietModeEnabledAsync(
@@ -606,10 +620,11 @@ public final class UserManagerServiceTest {
@Test
public void testAutoLockOnDeviceLockForPrivateProfile_keyguardUnlocked() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
UserManagerService mSpiedUms = spy(mUms);
UserInfo privateProfileUser =
- mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
+ mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK);
@@ -623,10 +638,11 @@ public final class UserManagerServiceTest {
@Test
public void testAutoLockOnDeviceLockForPrivateProfile_flagDisabled() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
mSetFlagsRule.disableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
UserManagerService mSpiedUms = spy(mUms);
UserInfo privateProfileUser =
- mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
+ mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
mSpiedUms.tryAutoLockingPrivateSpaceOnKeyguardChanged(true);
@@ -641,13 +657,14 @@ public final class UserManagerServiceTest {
@Test
public void testAutoLockAfterInactityForPrivateProfile() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
UserManagerService mSpiedUms = spy(mUms);
mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY);
when(mPowerManager.isInteractive()).thenReturn(false);
UserInfo privateProfileUser =
- mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
+ mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
Mockito.doNothing().when(mSpiedUms).scheduleMessageToAutoLockPrivateSpace(
eq(privateProfileUser.getUserHandle().getIdentifier()), any(),
@@ -662,6 +679,7 @@ public final class UserManagerServiceTest {
@Test
public void testSetOrUpdateAutoLockPreference_noPrivateProfile() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
mUms.setOrUpdateAutoLockPreferenceForPrivateProfile(
@@ -675,8 +693,9 @@ public final class UserManagerServiceTest {
@Test
public void testSetOrUpdateAutoLockPreference() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE);
- mUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile",
+ mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
USER_TYPE_PROFILE_PRIVATE, 0, 0, null);
// Set the preference to auto lock on device lock
@@ -733,6 +752,77 @@ public final class UserManagerServiceTest {
}
}
+ @Test
+ public void testCreatePrivateProfileOnHeadlessSystemUser_shouldAllowCreation() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+ UserManagerService mSpiedUms = spy(mUms);
+ int mainUser = mSpiedUms.getMainUserId();
+ doReturn(true).when(mSpiedUms).isHeadlessSystemUserMode();
+ assertThat(mSpiedUms.canAddPrivateProfile(mainUser)).isTrue();
+ assertThat(mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow(
+ PRIVATE_PROFILE_NAME, USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null)).isNotNull();
+ }
+
+ @Test
+ public void testCreatePrivateProfileOnSecondaryUser_shouldNotAllowCreation() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+ UserInfo user = mUms.createUserWithThrow(generateLongString(), USER_TYPE_FULL_SECONDARY, 0);
+ assertThat(mUms.canAddPrivateProfile(user.id)).isFalse();
+ assertThrows(ServiceSpecificException.class,
+ () -> mUms.createProfileForUserWithThrow(PRIVATE_PROFILE_NAME,
+ USER_TYPE_PROFILE_PRIVATE, 0, user.id, null));
+ }
+
+ @Test
+ public void testCreatePrivateProfileOnAutoDevices_shouldNotAllowCreation() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+ doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_AUTOMOTIVE), anyInt());
+ int mainUser = mUms.getMainUserId();
+ assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+ assertThrows(ServiceSpecificException.class,
+ () -> mUms.createProfileForUserWithThrow(PRIVATE_PROFILE_NAME,
+ USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
+ }
+
+ @Test
+ public void testCreatePrivateProfileOnTV_shouldNotAllowCreation() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+ doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_LEANBACK), anyInt());
+ int mainUser = mUms.getMainUserId();
+ assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+ assertThrows(ServiceSpecificException.class,
+ () -> mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
+ USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
+ }
+
+ @Test
+ public void testCreatePrivateProfileOnEmbedded_shouldNotAllowCreation() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+ doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_EMBEDDED), anyInt());
+ int mainUser = mUms.getMainUserId();
+ assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+ assertThrows(ServiceSpecificException.class,
+ () -> mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
+ USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
+ }
+
+ @Test
+ public void testCreatePrivateProfileOnWatch_shouldNotAllowCreation() {
+ mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ mSetFlagsRule.enableFlags(Flags.FLAG_BLOCK_PRIVATE_SPACE_CREATION);
+ doReturn(true).when(mMockPms).hasSystemFeature(eq(FEATURE_WATCH), anyInt());
+ int mainUser = mUms.getMainUserId();
+ assertThat(mUms.canAddPrivateProfile(0)).isFalse();
+ assertThrows(ServiceSpecificException.class,
+ () -> mUms.createProfileForUserEvenWhenDisallowedWithThrow(PRIVATE_PROFILE_NAME,
+ USER_TYPE_PROFILE_PRIVATE, 0, mainUser, null));
+ }
+
/**
* Returns true if the user's XML file has Default restrictions
* @param userId Id of the user.
@@ -800,6 +890,10 @@ public final class UserManagerServiceTest {
any(), eq(android.provider.Settings.Global.USER_SWITCHER_ENABLED), anyInt()));
}
+ private void mockIsLowRamDevice(boolean isLowRamDevice) {
+ doReturn(isLowRamDevice).when(ActivityManager::isLowRamDeviceStatic);
+ }
+
private void mockDeviceDemoMode(boolean enabled) {
doReturn(enabled ? 1 : 0).when(() -> Settings.Global.getInt(
any(), eq(android.provider.Settings.Global.DEVICE_DEMO_MODE), anyInt()));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 507b3fe62e29..1591a963a406 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -316,6 +316,10 @@ public final class UserManagerTest {
.that(userTypeDetails).isNotNull();
final UserProperties typeProps = userTypeDetails.getDefaultUserPropertiesReference();
+ // Only run the test if private profile creation is enabled on the device
+ assumeTrue("Private profile not enabled on the device",
+ mUserManager.canAddPrivateProfile());
+
// Test that only one private profile can be created
final int mainUserId = mainUser.getIdentifier();
UserInfo userInfo = createProfileForUser("Private profile1",
@@ -1231,6 +1235,20 @@ public final class UserManagerTest {
@MediumTest
@Test
+ public void testPrivateProfileCreationRestrictions() {
+ assumeTrue(mUserManager.canAddPrivateProfile());
+ final int mainUserId = ActivityManager.getCurrentUser();
+ try {
+ UserInfo privateProfileInfo = createProfileForUser("Private",
+ UserManager.USER_TYPE_PROFILE_PRIVATE, mainUserId);
+ assertThat(privateProfileInfo).isNotNull();
+ } catch (Exception e) {
+ fail("Creation of private profile failed due to " + e.getMessage());
+ }
+ }
+
+ @MediumTest
+ @Test
public void testAddRestrictedProfile() throws Exception {
if (isAutomotive() || UserManager.isHeadlessSystemUserMode()) return;
assertWithMessage("There should be no associated restricted profiles before the test")