Loading core/api/system-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -4232,6 +4232,7 @@ package android.content.pm { public final class UserProperties implements android.os.Parcelable { method public int describeContents(); method public int getCrossProfileContentSharingStrategy(); method @FlaggedApi("android.multiuser.support_hiding_profiles") @NonNull public int getProfileApiVisibility(); method public int getShowInQuietMode(); method public int getShowInSharingSurfaces(); method public boolean isCredentialShareableWithParent(); Loading @@ -4241,6 +4242,9 @@ package android.content.pm { field public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1; // 0x1 field public static final int CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION = 0; // 0x0 field public static final int CROSS_PROFILE_CONTENT_SHARING_UNKNOWN = -1; // 0xffffffff field @FlaggedApi("android.multiuser.support_hiding_profiles") public static final int PROFILE_API_VISIBILITY_HIDDEN = 1; // 0x1 field @FlaggedApi("android.multiuser.support_hiding_profiles") public static final int PROFILE_API_VISIBILITY_UNKNOWN = -1; // 0xffffffff field @FlaggedApi("android.multiuser.support_hiding_profiles") public static final int PROFILE_API_VISIBILITY_VISIBLE = 0; // 0x0 field public static final int SHOW_IN_QUIET_MODE_DEFAULT = 2; // 0x2 field public static final int SHOW_IN_QUIET_MODE_HIDDEN = 1; // 0x1 field public static final int SHOW_IN_QUIET_MODE_PAUSED = 0; // 0x0 core/java/android/content/pm/UserProperties.java +103 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.content.pm; import static android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -73,7 +76,7 @@ public final class UserProperties implements Parcelable { private static final String ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = "crossProfileContentSharingStrategy"; private static final String ATTR_PROFILE_API_VISIBILITY = "profileApiVisibility"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { INDEX_SHOW_IN_LAUNCHER, Loading @@ -93,6 +96,7 @@ public final class UserProperties implements Parcelable { INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE, INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY, INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING, INDEX_PROFILE_API_VISIBILITY }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { Loading @@ -114,6 +118,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14; private static final int INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = 15; private static final int INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING = 16; private static final int INDEX_PROFILE_API_VISIBILITY = 17; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; Loading Loading @@ -450,6 +455,41 @@ public final class UserProperties implements Parcelable { @SuppressLint("UnflaggedApi") // b/306636213 public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1; /** * Possible values for the profile visibility in public API surfaces. This indicates whether or * not the information linked to the profile (userId, package names) should not be returned in * API surfaces if a user is marked as hidden. * * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "PROFILE_API_VISIBILITY_", value = { PROFILE_API_VISIBILITY_UNKNOWN, PROFILE_API_VISIBILITY_VISIBLE, PROFILE_API_VISIBILITY_HIDDEN, } ) public @interface ProfileApiVisibility { } /* * The api visibility value for this profile user is undefined or unknown. */ @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public static final int PROFILE_API_VISIBILITY_UNKNOWN = -1; /** * Indicates that information about this profile user should be shown in API surfaces. */ @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public static final int PROFILE_API_VISIBILITY_VISIBLE = 0; /** * Indicates that information about this profile should be not be visible in API surfaces. */ @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public static final int PROFILE_API_VISIBILITY_HIDDEN = 1; /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given Loading Loading @@ -510,6 +550,9 @@ public final class UserProperties implements Parcelable { setShowInQuietMode(orig.getShowInQuietMode()); setShowInSharingSurfaces(orig.getShowInSharingSurfaces()); setCrossProfileContentSharingStrategy(orig.getCrossProfileContentSharingStrategy()); if (android.multiuser.Flags.supportHidingProfiles()) { setProfileApiVisibility(orig.getProfileApiVisibility()); } } /** Loading Loading @@ -951,9 +994,31 @@ public final class UserProperties implements Parcelable { } private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy; /** * Returns the visibility of the profile user in API surfaces. Any information linked to the * profile (userId, package names) should be hidden API surfaces if a user is marked as hidden. */ @NonNull @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public @ProfileApiVisibility int getProfileApiVisibility() { if (isPresent(INDEX_PROFILE_API_VISIBILITY)) return mProfileApiVisibility; if (mDefaultProperties != null) return mDefaultProperties.mProfileApiVisibility; throw new SecurityException("You don't have permission to query profileApiVisibility"); } /** @hide */ @NonNull @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public void setProfileApiVisibility(@ProfileApiVisibility int profileApiVisibility) { this.mProfileApiVisibility = profileApiVisibility; setPresent(INDEX_PROFILE_API_VISIBILITY); } private @ProfileApiVisibility int mProfileApiVisibility; @Override public String toString() { String profileApiVisibility = android.multiuser.Flags.supportHidingProfiles() ? ", mProfileApiVisibility=" + getProfileApiVisibility() : ""; // Please print in increasing order of PropertyIndex. return "UserProperties{" + "mPropertiesPresent=" + Long.toBinaryString(mPropertiesPresent) Loading @@ -977,6 +1042,7 @@ public final class UserProperties implements Parcelable { + ", mDeleteAppWithParent=" + getDeleteAppWithParent() + ", mAlwaysVisible=" + getAlwaysVisible() + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy() + profileApiVisibility + "}"; } Loading Loading @@ -1010,6 +1076,9 @@ public final class UserProperties implements Parcelable { pw.println(prefix + " mAlwaysVisible=" + getAlwaysVisible()); pw.println(prefix + " mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy()); if (android.multiuser.Flags.supportHidingProfiles()) { pw.println(prefix + " mProfileApiVisibility=" + getProfileApiVisibility()); } } /** Loading Loading @@ -1093,6 +1162,12 @@ public final class UserProperties implements Parcelable { break; case ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY: setCrossProfileContentSharingStrategy(parser.getAttributeInt(i)); break; case ATTR_PROFILE_API_VISIBILITY: if (android.multiuser.Flags.supportHidingProfiles()) { setProfileApiVisibility(parser.getAttributeInt(i)); } break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } Loading Loading @@ -1175,6 +1250,12 @@ public final class UserProperties implements Parcelable { serializer.attributeInt(null, ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY, mCrossProfileContentSharingStrategy); } if (isPresent(INDEX_PROFILE_API_VISIBILITY)) { if (android.multiuser.Flags.supportHidingProfiles()) { serializer.attributeInt(null, ATTR_PROFILE_API_VISIBILITY, mProfileApiVisibility); } } } // For use only with an object that has already had any permission-lacking fields stripped out. Loading @@ -1198,6 +1279,7 @@ public final class UserProperties implements Parcelable { dest.writeBoolean(mDeleteAppWithParent); dest.writeBoolean(mAlwaysVisible); dest.writeInt(mCrossProfileContentSharingStrategy); dest.writeInt(mProfileApiVisibility); } /** Loading Loading @@ -1225,6 +1307,7 @@ public final class UserProperties implements Parcelable { mDeleteAppWithParent = source.readBoolean(); mAlwaysVisible = source.readBoolean(); mCrossProfileContentSharingStrategy = source.readInt(); mProfileApiVisibility = source.readInt(); } @Override Loading Loading @@ -1274,6 +1357,7 @@ public final class UserProperties implements Parcelable { private boolean mAlwaysVisible = false; private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy = CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION; private @ProfileApiVisibility int mProfileApiVisibility = 0; /** * @hide Loading Loading @@ -1428,6 +1512,17 @@ public final class UserProperties implements Parcelable { return this; } /** * Sets the value for {@link #mProfileApiVisibility} * @hide */ @NonNull @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public Builder setProfileApiVisibility(@ProfileApiVisibility int profileApiVisibility){ mProfileApiVisibility = profileApiVisibility; return this; } /** Builds a UserProperties object with *all* values populated. * @hide */ Loading @@ -1452,7 +1547,8 @@ public final class UserProperties implements Parcelable { mAllowStoppingUserWithDelayedLocking, mDeleteAppWithParent, mAlwaysVisible, mCrossProfileContentSharingStrategy); mCrossProfileContentSharingStrategy, mProfileApiVisibility); } } // end Builder Loading @@ -1473,7 +1569,8 @@ public final class UserProperties implements Parcelable { boolean allowStoppingUserWithDelayedLocking, boolean deleteAppWithParent, boolean alwaysVisible, @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) { @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy, @ProfileApiVisibility int profileApiVisibility) { mDefaultProperties = null; setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); Loading @@ -1493,5 +1590,8 @@ public final class UserProperties implements Parcelable { setDeleteAppWithParent(deleteAppWithParent); setAlwaysVisible(alwaysVisible); setCrossProfileContentSharingStrategy(crossProfileContentSharingStrategy); if (android.multiuser.Flags.supportHidingProfiles()) { setProfileApiVisibility(profileApiVisibility); } } } core/java/android/content/pm/multiuser.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -100,3 +100,11 @@ flag { description: "Enable only the API changes to support private space" bug: "299069460" } flag { name: "support_hiding_profiles" namespace: "profile_experiences" description: "Allow the use of a hide_profile property to hide some profiles behind a permission" bug: "316362775" is_fixed_read_only: true } services/core/java/com/android/server/pm/UserTypeFactory.java +23 −17 Original line number Diff line number Diff line Loading @@ -288,6 +288,28 @@ public final class UserTypeFactory { * configuration. */ private static UserTypeDetails.Builder getDefaultTypeProfilePrivate() { UserProperties.Builder userPropertiesBuilder = new UserProperties.Builder() .setStartWithParent(true) .setCredentialShareableWithParent(true) .setAuthAlwaysRequiredToDisableQuietMode(true) .setAllowStoppingUserWithDelayedLocking(true) .setMediaSharedWithParent(false) .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE) .setShowInQuietMode( UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) .setShowInSharingSurfaces( UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT) .setCrossProfileContentSharingStrategy( UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT); if (android.multiuser.Flags.supportHidingProfiles()) { userPropertiesBuilder.setProfileApiVisibility( UserProperties.PROFILE_API_VISIBILITY_HIDDEN); } return new UserTypeDetails.Builder() .setName(USER_TYPE_PROFILE_PRIVATE) .setBaseType(FLAG_PROFILE) Loading @@ -306,23 +328,7 @@ public final class UserTypeFactory { .setDarkThemeBadgeColors( R.color.white) .setDefaultRestrictions(getDefaultProfileRestrictions()) .setDefaultUserProperties(new UserProperties.Builder() .setStartWithParent(true) .setCredentialShareableWithParent(true) .setAuthAlwaysRequiredToDisableQuietMode(true) .setAllowStoppingUserWithDelayedLocking(true) .setMediaSharedWithParent(false) .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE) .setShowInQuietMode( UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) .setShowInSharingSurfaces( UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT) .setCrossProfileContentSharingStrategy( UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT)); .setDefaultUserProperties(userPropertiesBuilder); } /** Loading services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java +13 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static org.testng.Assert.assertThrows; import android.content.pm.UserProperties; import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Xml; import androidx.test.filters.MediumTest; Loading @@ -31,6 +32,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -52,10 +54,13 @@ import java.util.function.Supplier; @RunWith(AndroidJUnit4.class) @MediumTest public class UserManagerServiceUserPropertiesTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); /** Test that UserProperties can properly read the xml information that it writes. */ @Test public void testWriteReadXml() throws Exception { mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES); final UserProperties defaultProps = new UserProperties.Builder() .setShowInLauncher(21) .setStartWithParent(false) Loading @@ -73,6 +78,7 @@ public class UserManagerServiceUserPropertiesTest { .setDeleteAppWithParent(false) .setAlwaysVisible(false) .setCrossProfileContentSharingStrategy(0) .setProfileApiVisibility(34) .build(); final UserProperties actualProps = new UserProperties(defaultProps); actualProps.setShowInLauncher(14); Loading @@ -90,6 +96,7 @@ public class UserManagerServiceUserPropertiesTest { actualProps.setDeleteAppWithParent(true); actualProps.setAlwaysVisible(true); actualProps.setCrossProfileContentSharingStrategy(1); actualProps.setProfileApiVisibility(36); // Write the properties to xml. final ByteArrayOutputStream baos = new ByteArrayOutputStream(); Loading @@ -114,6 +121,7 @@ public class UserManagerServiceUserPropertiesTest { /** Tests parcelling an object in which all properties are present. */ @Test public void testParcelUnparcel() throws Exception { mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES); final UserProperties originalProps = new UserProperties.Builder() .setShowInLauncher(2145) .build(); Loading @@ -124,6 +132,7 @@ public class UserManagerServiceUserPropertiesTest { /** Tests copying a UserProperties object varying permissions. */ @Test public void testCopyLacksPermissions() throws Exception { mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES); final UserProperties defaultProps = new UserProperties.Builder() .setShowInLauncher(2145) .setStartWithParent(true) Loading @@ -134,6 +143,7 @@ public class UserManagerServiceUserPropertiesTest { .setAuthAlwaysRequiredToDisableQuietMode(false) .setAllowStoppingUserWithDelayedLocking(false) .setAlwaysVisible(true) .setProfileApiVisibility(110) .build(); final UserProperties orig = new UserProperties(defaultProps); orig.setShowInLauncher(2841); Loading Loading @@ -209,6 +219,8 @@ public class UserManagerServiceUserPropertiesTest { copy::isCredentialShareableWithParent, true); assertEqualGetterOrThrows(orig::getCrossProfileContentSharingStrategy, copy::getCrossProfileContentSharingStrategy, true); assertEqualGetterOrThrows(orig::getProfileApiVisibility, copy::getProfileApiVisibility, true); } /** Loading Loading @@ -270,5 +282,6 @@ public class UserManagerServiceUserPropertiesTest { assertThat(expected.getAlwaysVisible()).isEqualTo(actual.getAlwaysVisible()); assertThat(expected.getCrossProfileContentSharingStrategy()) .isEqualTo(actual.getCrossProfileContentSharingStrategy()); assertThat(expected.getProfileApiVisibility()).isEqualTo(actual.getProfileApiVisibility()); } } Loading
core/api/system-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -4232,6 +4232,7 @@ package android.content.pm { public final class UserProperties implements android.os.Parcelable { method public int describeContents(); method public int getCrossProfileContentSharingStrategy(); method @FlaggedApi("android.multiuser.support_hiding_profiles") @NonNull public int getProfileApiVisibility(); method public int getShowInQuietMode(); method public int getShowInSharingSurfaces(); method public boolean isCredentialShareableWithParent(); Loading @@ -4241,6 +4242,9 @@ package android.content.pm { field public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1; // 0x1 field public static final int CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION = 0; // 0x0 field public static final int CROSS_PROFILE_CONTENT_SHARING_UNKNOWN = -1; // 0xffffffff field @FlaggedApi("android.multiuser.support_hiding_profiles") public static final int PROFILE_API_VISIBILITY_HIDDEN = 1; // 0x1 field @FlaggedApi("android.multiuser.support_hiding_profiles") public static final int PROFILE_API_VISIBILITY_UNKNOWN = -1; // 0xffffffff field @FlaggedApi("android.multiuser.support_hiding_profiles") public static final int PROFILE_API_VISIBILITY_VISIBLE = 0; // 0x0 field public static final int SHOW_IN_QUIET_MODE_DEFAULT = 2; // 0x2 field public static final int SHOW_IN_QUIET_MODE_HIDDEN = 1; // 0x1 field public static final int SHOW_IN_QUIET_MODE_PAUSED = 0; // 0x0
core/java/android/content/pm/UserProperties.java +103 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.content.pm; import static android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -73,7 +76,7 @@ public final class UserProperties implements Parcelable { private static final String ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = "crossProfileContentSharingStrategy"; private static final String ATTR_PROFILE_API_VISIBILITY = "profileApiVisibility"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { INDEX_SHOW_IN_LAUNCHER, Loading @@ -93,6 +96,7 @@ public final class UserProperties implements Parcelable { INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE, INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY, INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING, INDEX_PROFILE_API_VISIBILITY }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { Loading @@ -114,6 +118,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14; private static final int INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = 15; private static final int INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING = 16; private static final int INDEX_PROFILE_API_VISIBILITY = 17; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; Loading Loading @@ -450,6 +455,41 @@ public final class UserProperties implements Parcelable { @SuppressLint("UnflaggedApi") // b/306636213 public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1; /** * Possible values for the profile visibility in public API surfaces. This indicates whether or * not the information linked to the profile (userId, package names) should not be returned in * API surfaces if a user is marked as hidden. * * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "PROFILE_API_VISIBILITY_", value = { PROFILE_API_VISIBILITY_UNKNOWN, PROFILE_API_VISIBILITY_VISIBLE, PROFILE_API_VISIBILITY_HIDDEN, } ) public @interface ProfileApiVisibility { } /* * The api visibility value for this profile user is undefined or unknown. */ @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public static final int PROFILE_API_VISIBILITY_UNKNOWN = -1; /** * Indicates that information about this profile user should be shown in API surfaces. */ @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public static final int PROFILE_API_VISIBILITY_VISIBLE = 0; /** * Indicates that information about this profile should be not be visible in API surfaces. */ @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public static final int PROFILE_API_VISIBILITY_HIDDEN = 1; /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given Loading Loading @@ -510,6 +550,9 @@ public final class UserProperties implements Parcelable { setShowInQuietMode(orig.getShowInQuietMode()); setShowInSharingSurfaces(orig.getShowInSharingSurfaces()); setCrossProfileContentSharingStrategy(orig.getCrossProfileContentSharingStrategy()); if (android.multiuser.Flags.supportHidingProfiles()) { setProfileApiVisibility(orig.getProfileApiVisibility()); } } /** Loading Loading @@ -951,9 +994,31 @@ public final class UserProperties implements Parcelable { } private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy; /** * Returns the visibility of the profile user in API surfaces. Any information linked to the * profile (userId, package names) should be hidden API surfaces if a user is marked as hidden. */ @NonNull @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public @ProfileApiVisibility int getProfileApiVisibility() { if (isPresent(INDEX_PROFILE_API_VISIBILITY)) return mProfileApiVisibility; if (mDefaultProperties != null) return mDefaultProperties.mProfileApiVisibility; throw new SecurityException("You don't have permission to query profileApiVisibility"); } /** @hide */ @NonNull @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public void setProfileApiVisibility(@ProfileApiVisibility int profileApiVisibility) { this.mProfileApiVisibility = profileApiVisibility; setPresent(INDEX_PROFILE_API_VISIBILITY); } private @ProfileApiVisibility int mProfileApiVisibility; @Override public String toString() { String profileApiVisibility = android.multiuser.Flags.supportHidingProfiles() ? ", mProfileApiVisibility=" + getProfileApiVisibility() : ""; // Please print in increasing order of PropertyIndex. return "UserProperties{" + "mPropertiesPresent=" + Long.toBinaryString(mPropertiesPresent) Loading @@ -977,6 +1042,7 @@ public final class UserProperties implements Parcelable { + ", mDeleteAppWithParent=" + getDeleteAppWithParent() + ", mAlwaysVisible=" + getAlwaysVisible() + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy() + profileApiVisibility + "}"; } Loading Loading @@ -1010,6 +1076,9 @@ public final class UserProperties implements Parcelable { pw.println(prefix + " mAlwaysVisible=" + getAlwaysVisible()); pw.println(prefix + " mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy()); if (android.multiuser.Flags.supportHidingProfiles()) { pw.println(prefix + " mProfileApiVisibility=" + getProfileApiVisibility()); } } /** Loading Loading @@ -1093,6 +1162,12 @@ public final class UserProperties implements Parcelable { break; case ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY: setCrossProfileContentSharingStrategy(parser.getAttributeInt(i)); break; case ATTR_PROFILE_API_VISIBILITY: if (android.multiuser.Flags.supportHidingProfiles()) { setProfileApiVisibility(parser.getAttributeInt(i)); } break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } Loading Loading @@ -1175,6 +1250,12 @@ public final class UserProperties implements Parcelable { serializer.attributeInt(null, ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY, mCrossProfileContentSharingStrategy); } if (isPresent(INDEX_PROFILE_API_VISIBILITY)) { if (android.multiuser.Flags.supportHidingProfiles()) { serializer.attributeInt(null, ATTR_PROFILE_API_VISIBILITY, mProfileApiVisibility); } } } // For use only with an object that has already had any permission-lacking fields stripped out. Loading @@ -1198,6 +1279,7 @@ public final class UserProperties implements Parcelable { dest.writeBoolean(mDeleteAppWithParent); dest.writeBoolean(mAlwaysVisible); dest.writeInt(mCrossProfileContentSharingStrategy); dest.writeInt(mProfileApiVisibility); } /** Loading Loading @@ -1225,6 +1307,7 @@ public final class UserProperties implements Parcelable { mDeleteAppWithParent = source.readBoolean(); mAlwaysVisible = source.readBoolean(); mCrossProfileContentSharingStrategy = source.readInt(); mProfileApiVisibility = source.readInt(); } @Override Loading Loading @@ -1274,6 +1357,7 @@ public final class UserProperties implements Parcelable { private boolean mAlwaysVisible = false; private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy = CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION; private @ProfileApiVisibility int mProfileApiVisibility = 0; /** * @hide Loading Loading @@ -1428,6 +1512,17 @@ public final class UserProperties implements Parcelable { return this; } /** * Sets the value for {@link #mProfileApiVisibility} * @hide */ @NonNull @FlaggedApi(FLAG_SUPPORT_HIDING_PROFILES) public Builder setProfileApiVisibility(@ProfileApiVisibility int profileApiVisibility){ mProfileApiVisibility = profileApiVisibility; return this; } /** Builds a UserProperties object with *all* values populated. * @hide */ Loading @@ -1452,7 +1547,8 @@ public final class UserProperties implements Parcelable { mAllowStoppingUserWithDelayedLocking, mDeleteAppWithParent, mAlwaysVisible, mCrossProfileContentSharingStrategy); mCrossProfileContentSharingStrategy, mProfileApiVisibility); } } // end Builder Loading @@ -1473,7 +1569,8 @@ public final class UserProperties implements Parcelable { boolean allowStoppingUserWithDelayedLocking, boolean deleteAppWithParent, boolean alwaysVisible, @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) { @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy, @ProfileApiVisibility int profileApiVisibility) { mDefaultProperties = null; setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); Loading @@ -1493,5 +1590,8 @@ public final class UserProperties implements Parcelable { setDeleteAppWithParent(deleteAppWithParent); setAlwaysVisible(alwaysVisible); setCrossProfileContentSharingStrategy(crossProfileContentSharingStrategy); if (android.multiuser.Flags.supportHidingProfiles()) { setProfileApiVisibility(profileApiVisibility); } } }
core/java/android/content/pm/multiuser.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -100,3 +100,11 @@ flag { description: "Enable only the API changes to support private space" bug: "299069460" } flag { name: "support_hiding_profiles" namespace: "profile_experiences" description: "Allow the use of a hide_profile property to hide some profiles behind a permission" bug: "316362775" is_fixed_read_only: true }
services/core/java/com/android/server/pm/UserTypeFactory.java +23 −17 Original line number Diff line number Diff line Loading @@ -288,6 +288,28 @@ public final class UserTypeFactory { * configuration. */ private static UserTypeDetails.Builder getDefaultTypeProfilePrivate() { UserProperties.Builder userPropertiesBuilder = new UserProperties.Builder() .setStartWithParent(true) .setCredentialShareableWithParent(true) .setAuthAlwaysRequiredToDisableQuietMode(true) .setAllowStoppingUserWithDelayedLocking(true) .setMediaSharedWithParent(false) .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE) .setShowInQuietMode( UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) .setShowInSharingSurfaces( UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT) .setCrossProfileContentSharingStrategy( UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT); if (android.multiuser.Flags.supportHidingProfiles()) { userPropertiesBuilder.setProfileApiVisibility( UserProperties.PROFILE_API_VISIBILITY_HIDDEN); } return new UserTypeDetails.Builder() .setName(USER_TYPE_PROFILE_PRIVATE) .setBaseType(FLAG_PROFILE) Loading @@ -306,23 +328,7 @@ public final class UserTypeFactory { .setDarkThemeBadgeColors( R.color.white) .setDefaultRestrictions(getDefaultProfileRestrictions()) .setDefaultUserProperties(new UserProperties.Builder() .setStartWithParent(true) .setCredentialShareableWithParent(true) .setAuthAlwaysRequiredToDisableQuietMode(true) .setAllowStoppingUserWithDelayedLocking(true) .setMediaSharedWithParent(false) .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE) .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE) .setShowInQuietMode( UserProperties.SHOW_IN_QUIET_MODE_HIDDEN) .setShowInSharingSurfaces( UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT) .setCrossProfileContentSharingStrategy( UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT)); .setDefaultUserProperties(userPropertiesBuilder); } /** Loading
services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java +13 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static org.testng.Assert.assertThrows; import android.content.pm.UserProperties; import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.util.Xml; import androidx.test.filters.MediumTest; Loading @@ -31,6 +32,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -52,10 +54,13 @@ import java.util.function.Supplier; @RunWith(AndroidJUnit4.class) @MediumTest public class UserManagerServiceUserPropertiesTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); /** Test that UserProperties can properly read the xml information that it writes. */ @Test public void testWriteReadXml() throws Exception { mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES); final UserProperties defaultProps = new UserProperties.Builder() .setShowInLauncher(21) .setStartWithParent(false) Loading @@ -73,6 +78,7 @@ public class UserManagerServiceUserPropertiesTest { .setDeleteAppWithParent(false) .setAlwaysVisible(false) .setCrossProfileContentSharingStrategy(0) .setProfileApiVisibility(34) .build(); final UserProperties actualProps = new UserProperties(defaultProps); actualProps.setShowInLauncher(14); Loading @@ -90,6 +96,7 @@ public class UserManagerServiceUserPropertiesTest { actualProps.setDeleteAppWithParent(true); actualProps.setAlwaysVisible(true); actualProps.setCrossProfileContentSharingStrategy(1); actualProps.setProfileApiVisibility(36); // Write the properties to xml. final ByteArrayOutputStream baos = new ByteArrayOutputStream(); Loading @@ -114,6 +121,7 @@ public class UserManagerServiceUserPropertiesTest { /** Tests parcelling an object in which all properties are present. */ @Test public void testParcelUnparcel() throws Exception { mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES); final UserProperties originalProps = new UserProperties.Builder() .setShowInLauncher(2145) .build(); Loading @@ -124,6 +132,7 @@ public class UserManagerServiceUserPropertiesTest { /** Tests copying a UserProperties object varying permissions. */ @Test public void testCopyLacksPermissions() throws Exception { mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SUPPORT_HIDING_PROFILES); final UserProperties defaultProps = new UserProperties.Builder() .setShowInLauncher(2145) .setStartWithParent(true) Loading @@ -134,6 +143,7 @@ public class UserManagerServiceUserPropertiesTest { .setAuthAlwaysRequiredToDisableQuietMode(false) .setAllowStoppingUserWithDelayedLocking(false) .setAlwaysVisible(true) .setProfileApiVisibility(110) .build(); final UserProperties orig = new UserProperties(defaultProps); orig.setShowInLauncher(2841); Loading Loading @@ -209,6 +219,8 @@ public class UserManagerServiceUserPropertiesTest { copy::isCredentialShareableWithParent, true); assertEqualGetterOrThrows(orig::getCrossProfileContentSharingStrategy, copy::getCrossProfileContentSharingStrategy, true); assertEqualGetterOrThrows(orig::getProfileApiVisibility, copy::getProfileApiVisibility, true); } /** Loading Loading @@ -270,5 +282,6 @@ public class UserManagerServiceUserPropertiesTest { assertThat(expected.getAlwaysVisible()).isEqualTo(actual.getAlwaysVisible()); assertThat(expected.getCrossProfileContentSharingStrategy()) .isEqualTo(actual.getCrossProfileContentSharingStrategy()); assertThat(expected.getProfileApiVisibility()).isEqualTo(actual.getProfileApiVisibility()); } }