diff options
| author | 2023-06-30 13:46:44 +0000 | |
|---|---|---|
| committer | 2023-06-30 13:46:44 +0000 | |
| commit | aa10ad938e7989f43b120169fa4092253602fd2a (patch) | |
| tree | 33644a6f2059da9d7b2447ad86b6ea2aec5ea0e4 | |
| parent | 382508e8a2c71535254379ca697840dbdfbdf62e (diff) | |
| parent | 95e76bc49851366edfa88da9448caf983adc287a (diff) | |
Merge "Added Private profile user type"
6 files changed, 129 insertions, 0 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index bac3f4a75973..7c3d8fb856a4 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1061,6 +1061,7 @@ package android.content.pm { method public boolean isMain(); method public boolean isManagedProfile(); method @Deprecated public boolean isPrimary(); + method public boolean isPrivateProfile(); method public boolean isProfile(); method public boolean isQuietModeEnabled(); method public boolean isRestricted(); diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index 7f42c1a08f9c..9f4459d6591b 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -390,6 +390,10 @@ public class UserInfo implements Parcelable { return UserManager.isUserTypeCommunalProfile(userType); } + public boolean isPrivateProfile() { + return UserManager.isUserTypePrivateProfile(userType); + } + @UnsupportedAppUsage public boolean isEnabled() { return (flags & FLAG_DISABLED) != FLAG_DISABLED; diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 84dc79b92c55..ba1f979b4514 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -159,6 +159,13 @@ public class UserManager { @SystemApi public static final String USER_TYPE_PROFILE_CLONE = "android.os.usertype.profile.CLONE"; + + /** + * User type representing a private profile. + * @hide + */ + public static final String USER_TYPE_PROFILE_PRIVATE = "android.os.usertype.profile.PRIVATE"; + /** * User type representing a generic profile for testing purposes. Only on debuggable builds. * @hide @@ -2858,6 +2865,16 @@ public class UserManager { } /** + * Returns whether the user type is a + * {@link UserManager#USER_TYPE_PROFILE_PRIVATE private profile}. + * + * @hide + */ + public static boolean isUserTypePrivateProfile(@Nullable String userType) { + return USER_TYPE_PROFILE_PRIVATE.equals(userType); + } + + /** * @hide * @deprecated Use {@link #isRestrictedProfile()} */ @@ -3146,6 +3163,24 @@ public class UserManager { } /** + * Checks if the context user is a private profile. + * + * @return whether the context user is a private profile. + * + * @see android.os.UserManager#USER_TYPE_PROFILE_PRIVATE + * @hide + */ + @UserHandleAware( + requiresAnyOfPermissionsIfNotCallerProfileGroup = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.QUERY_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + @SuppressAutoDoc + public boolean isPrivateProfile() { + return isUserTypePrivateProfile(getProfileType()); + } + + /** * Checks if the context user is an ephemeral user. * * @return whether the context user is an ephemeral user. diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java index 9ebb8d6ac4be..7bdcd685a2e9 100644 --- a/services/core/java/com/android/server/pm/UserTypeDetails.java +++ b/services/core/java/com/android/server/pm/UserTypeDetails.java @@ -633,4 +633,12 @@ public final class UserTypeDetails { public boolean isCommunalProfile() { return UserManager.isUserTypeCommunalProfile(mName); } + + /** + * Returns whether the user type is a private profile + * (i.e. {@link UserManager#USER_TYPE_PROFILE_PRIVATE}). + */ + public boolean isPrivateProfile() { + return UserManager.isUserTypePrivateProfile(mName); + } } diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 1569e06bd06d..f7967c0a60d9 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -35,6 +35,7 @@ import static android.os.UserManager.USER_TYPE_FULL_SYSTEM; import static android.os.UserManager.USER_TYPE_PROFILE_CLONE; import static android.os.UserManager.USER_TYPE_PROFILE_COMMUNAL; import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED; +import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE; import static android.os.UserManager.USER_TYPE_PROFILE_TEST; import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS; @@ -108,6 +109,7 @@ public final class UserTypeFactory { builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless()); builders.put(USER_TYPE_PROFILE_CLONE, getDefaultTypeProfileClone()); builders.put(USER_TYPE_PROFILE_COMMUNAL, getDefaultTypeProfileCommunal()); + builders.put(USER_TYPE_PROFILE_PRIVATE, getDefaultTypeProfilePrivate()); if (Build.IS_DEBUGGABLE) { builders.put(USER_TYPE_PROFILE_TEST, getDefaultTypeProfileTest()); } @@ -264,6 +266,39 @@ public final class UserTypeFactory { } /** + * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_PRIVATE} + * configuration. + */ + private static UserTypeDetails.Builder getDefaultTypeProfilePrivate() { + return new UserTypeDetails.Builder() + .setName(USER_TYPE_PROFILE_PRIVATE) + .setBaseType(FLAG_PROFILE) + .setMaxAllowedPerParent(1) + .setLabel(0) + .setIconBadge(com.android.internal.R.drawable.ic_test_icon_badge_experiment) + .setBadgePlain(com.android.internal.R.drawable.ic_test_badge_experiment) + .setBadgeNoBackground(com.android.internal.R.drawable.ic_test_badge_no_background) + .setStatusBarIcon(com.android.internal.R.drawable.ic_test_badge_experiment) + .setBadgeLabels( + com.android.internal.R.string.managed_profile_label_badge, + com.android.internal.R.string.managed_profile_label_badge_2, + com.android.internal.R.string.managed_profile_label_badge_3) + .setBadgeColors( + com.android.internal.R.color.profile_badge_2) + .setDarkThemeBadgeColors( + com.android.internal.R.color.profile_badge_2_dark) + .setDefaultRestrictions(getDefaultProfileRestrictions()) + .setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings()) + .setDefaultUserProperties(new UserProperties.Builder() + .setStartWithParent(true) + .setCredentialShareableWithParent(false) + .setMediaSharedWithParent(false) + .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) + .setCrossProfileIntentFilterAccessControl( + UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM)); + } + + /** * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SECONDARY} * configuration. */ 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 7d0f36133a9c..dd681aa85c3f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -265,6 +265,52 @@ public final class UserManagerTest { assertWithMessage("Communal profile not visible").that(umCommunal.isUserVisible()).isTrue(); } + @Test + public void testPrivateProfile() throws Exception { + UserHandle mainUser = mUserManager.getMainUser(); + assumeTrue("Main user is null", mainUser != null); + // Get the default properties for private profile user type. + final UserTypeDetails userTypeDetails = + UserTypeFactory.getUserTypes().get(UserManager.USER_TYPE_PROFILE_PRIVATE); + assertWithMessage("No %s type on device", UserManager.USER_TYPE_PROFILE_PRIVATE) + .that(userTypeDetails).isNotNull(); + final UserProperties typeProps = userTypeDetails.getDefaultUserPropertiesReference(); + + // Test that only one private profile can be created + final int mainUserId = mainUser.getIdentifier(); + UserInfo userInfo = createProfileForUser("Private profile1", + UserManager.USER_TYPE_PROFILE_PRIVATE, + mainUserId); + assertThat(userInfo).isNotNull(); + UserInfo userInfo2 = createProfileForUser("Private profile2", + UserManager.USER_TYPE_PROFILE_PRIVATE, + mainUserId); + assertThat(userInfo2).isNull(); + + // Check that the new private profile has the expected properties (relative to the defaults) + // provided that the test caller has the necessary permissions. + UserProperties privateProfileUserProperties = + mUserManager.getUserProperties(UserHandle.of(userInfo.id)); + assertThat(typeProps.getShowInLauncher()) + .isEqualTo(privateProfileUserProperties.getShowInLauncher()); + assertThrows(SecurityException.class, privateProfileUserProperties::getStartWithParent); + assertThrows(SecurityException.class, + privateProfileUserProperties::getCrossProfileIntentFilterAccessControl); + assertThat(typeProps.isMediaSharedWithParent()) + .isEqualTo(privateProfileUserProperties.isMediaSharedWithParent()); + assertThat(typeProps.isCredentialShareableWithParent()) + .isEqualTo(privateProfileUserProperties.isCredentialShareableWithParent()); + assertThrows(SecurityException.class, privateProfileUserProperties::getDeleteAppWithParent); + + // Verify private profile parent + assertThat(mUserManager.getProfileParent(mainUserId)).isNull(); + UserInfo parentProfileInfo = mUserManager.getProfileParent(userInfo.id); + assertThat(parentProfileInfo).isNotNull(); + assertThat(mainUserId).isEqualTo(parentProfileInfo.id); + removeUser(userInfo.id); + assertThat(mUserManager.getProfileParent(mainUserId)).isNull(); + } + @MediumTest @Test public void testAdd2Users() throws Exception { |