diff options
| author | 2023-12-07 22:30:59 +0000 | |
|---|---|---|
| committer | 2023-12-07 22:30:59 +0000 | |
| commit | bbda2a3772ac88e191c20aa2516c240ebbfa7af6 (patch) | |
| tree | 352b5f984af185ec7b51b367b31e8578ab783fcd | |
| parent | 20c9e7aae56c0eb54ea0e430b958a8a358e6602f (diff) | |
| parent | 46e379dc53a7664cdb5f944834238daa8be47ae4 (diff) | |
Merge "Adding user property for CrossProfileContentSharingStrategy." into main
8 files changed, 145 insertions, 15 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 9b11b505e357..c64f2304db4e 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -4196,12 +4196,15 @@ package android.content.pm { public final class UserProperties implements android.os.Parcelable { method public int describeContents(); + method public int getCrossProfileContentSharingStrategy(); method public int getShowInQuietMode(); method public int getShowInSharingSurfaces(); method public boolean isCredentialShareableWithParent(); method public boolean isMediaSharedWithParent(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.UserProperties> CREATOR; + 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 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 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 7417137b3725..3f2376db8652 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1166,6 +1166,7 @@ package android.content.pm { public static final class UserProperties.Builder { ctor public UserProperties.Builder(); method @NonNull public android.content.pm.UserProperties build(); + method @NonNull public android.content.pm.UserProperties.Builder setCrossProfileContentSharingStrategy(int); method @NonNull public android.content.pm.UserProperties.Builder setShowInQuietMode(int); method @NonNull public android.content.pm.UserProperties.Builder setShowInSharingSurfaces(int); } diff --git a/core/java/android/content/pm/UserProperties.java b/core/java/android/content/pm/UserProperties.java index 56e8291f25e9..c4012688406d 100644 --- a/core/java/android/content/pm/UserProperties.java +++ b/core/java/android/content/pm/UserProperties.java @@ -69,6 +69,9 @@ public final class UserProperties implements Parcelable { private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent"; private static final String ATTR_ALWAYS_VISIBLE = "alwaysVisible"; + private static final String ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = + "crossProfileContentSharingStrategy"; + /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { INDEX_SHOW_IN_LAUNCHER, @@ -86,6 +89,7 @@ public final class UserProperties implements Parcelable { INDEX_SHOW_IN_QUIET_MODE, INDEX_SHOW_IN_SHARING_SURFACES, INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE, + INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { @@ -105,6 +109,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_SHOW_IN_QUIET_MODE = 12; private static final int INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE = 13; private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14; + private static final int INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = 15; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; @@ -365,6 +370,45 @@ public final class UserProperties implements Parcelable { */ @SuppressLint("UnflaggedApi") // b/306636213 public static final int SHOW_IN_SHARING_SURFACES_NO = SHOW_IN_LAUNCHER_NO; + /** + * Possible values for cross profile content sharing strategy for this profile. + * + * @hide + */ + @IntDef(prefix = {"CROSS_PROFILE_CONTENT_SHARING_STRATEGY_"}, value = { + CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION, + CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CrossProfileContentSharingStrategy { + } + + /** + * Signifies that cross-profile content sharing strategy, both to and from this profile, should + * not be delegated to any other user/profile. + * For ex: + * If this property is set for a profile, content sharing applications (such as Android + * Sharesheet), should not delegate the decision to share content between that profile and + * another profile to whether content sharing is allowed between any other profile/user related + * to those profiles. They should instead decide, based upon whether content sharing is + * specifically allowed between the two profiles in question. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION = 0; + + /** + * Signifies that cross-profile content sharing strategy, both to and from this profile, should + * be based upon the strategy used by the parent user of the profile. + * For ex: + * If this property is set for a profile A, content sharing applications (such as Android + * Sharesheet), should share content between profile A and profile B, based upon whether content + * sharing is allowed between the parent of profile A and profile B. + * If it's also set for profile B, then decision should, in turn be made by considering content + * sharing strategy between the parents of both profiles. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1; + /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given @@ -423,6 +467,7 @@ public final class UserProperties implements Parcelable { setCredentialShareableWithParent(orig.isCredentialShareableWithParent()); setShowInQuietMode(orig.getShowInQuietMode()); setShowInSharingSurfaces(orig.getShowInSharingSurfaces()); + setCrossProfileContentSharingStrategy(orig.getCrossProfileContentSharingStrategy()); } /** @@ -776,8 +821,7 @@ public final class UserProperties implements Parcelable { private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl; /** - * Returns the user's {@link CrossProfileIntentResolutionStrategy}. If not explicitly - * configured, default value is {@link #CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT}. + * Returns the user's {@link CrossProfileIntentResolutionStrategy}. * @return user's {@link CrossProfileIntentResolutionStrategy}. * * @hide @@ -792,11 +836,8 @@ public final class UserProperties implements Parcelable { throw new SecurityException("You don't have permission to query " + "crossProfileIntentResolutionStrategy"); } - /** - * Sets {@link CrossProfileIntentResolutionStrategy} for the user. - * @param val resolution strategy for user - * @hide - */ + + /** @hide */ public void setCrossProfileIntentResolutionStrategy( @CrossProfileIntentResolutionStrategy int val) { this.mCrossProfileIntentResolutionStrategy = val; @@ -804,6 +845,39 @@ public final class UserProperties implements Parcelable { } private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy; + /** + * Returns the user's {@link CrossProfileContentSharingStrategy}. + * + * Content sharing applications, such as Android Sharesheet allow sharing of content + * (an image, for ex.) between profiles, based upon cross-profile access checks between the + * originating and destined profile. + * In some cases however, we may want another user (such as profile parent) to serve as the + * delegated user to be used for such checks. + * To effect the same, clients can fetch this property and accordingly replace the + * originating/destined profile by another user for cross-profile access checks. + * + * @return user's {@link CrossProfileContentSharingStrategy}. + */ + @SuppressLint("UnflaggedApi") // b/306636213 + public @CrossProfileContentSharingStrategy int getCrossProfileContentSharingStrategy() { + if (isPresent(INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY)) { + return mCrossProfileContentSharingStrategy; + } + if (mDefaultProperties != null) { + return mDefaultProperties.mCrossProfileContentSharingStrategy; + } + throw new SecurityException("You don't have permission to query " + + "crossProfileContentSharingStrategy"); + } + + /** @hide */ + public void setCrossProfileContentSharingStrategy( + @CrossProfileContentSharingStrategy int val) { + this.mCrossProfileContentSharingStrategy = val; + setPresent(INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY); + } + private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy; + @Override public String toString() { @@ -827,6 +901,7 @@ public final class UserProperties implements Parcelable { + isAuthAlwaysRequiredToDisableQuietMode() + ", mDeleteAppWithParent=" + getDeleteAppWithParent() + ", mAlwaysVisible=" + getAlwaysVisible() + + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy() + "}"; } @@ -856,6 +931,8 @@ public final class UserProperties implements Parcelable { + isAuthAlwaysRequiredToDisableQuietMode()); pw.println(prefix + " mDeleteAppWithParent=" + getDeleteAppWithParent()); pw.println(prefix + " mAlwaysVisible=" + getAlwaysVisible()); + pw.println(prefix + " mCrossProfileContentSharingStrategy=" + + getCrossProfileContentSharingStrategy()); } /** @@ -934,6 +1011,8 @@ public final class UserProperties implements Parcelable { case ATTR_ALWAYS_VISIBLE: setAlwaysVisible(parser.getAttributeBoolean(i)); break; + case ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY: + setCrossProfileContentSharingStrategy(parser.getAttributeInt(i)); default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } @@ -1008,6 +1087,10 @@ public final class UserProperties implements Parcelable { serializer.attributeBoolean(null, ATTR_ALWAYS_VISIBLE, mAlwaysVisible); } + if (isPresent(INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY)) { + serializer.attributeInt(null, ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY, + mCrossProfileContentSharingStrategy); + } } // For use only with an object that has already had any permission-lacking fields stripped out. @@ -1029,6 +1112,7 @@ public final class UserProperties implements Parcelable { dest.writeBoolean(mAuthAlwaysRequiredToDisableQuietMode); dest.writeBoolean(mDeleteAppWithParent); dest.writeBoolean(mAlwaysVisible); + dest.writeInt(mCrossProfileContentSharingStrategy); } /** @@ -1054,6 +1138,7 @@ public final class UserProperties implements Parcelable { mAuthAlwaysRequiredToDisableQuietMode = source.readBoolean(); mDeleteAppWithParent = source.readBoolean(); mAlwaysVisible = source.readBoolean(); + mCrossProfileContentSharingStrategy = source.readInt(); } @Override @@ -1100,6 +1185,8 @@ public final class UserProperties implements Parcelable { private boolean mAuthAlwaysRequiredToDisableQuietMode = false; private boolean mDeleteAppWithParent = false; private boolean mAlwaysVisible = false; + private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy = + CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION; /** * @hide @@ -1231,6 +1318,19 @@ public final class UserProperties implements Parcelable { return this; } + /** Sets the value for {@link #mCrossProfileContentSharingStrategy} + * @hide + */ + + @TestApi + @SuppressLint("UnflaggedApi") // b/306636213 + @NonNull + public Builder setCrossProfileContentSharingStrategy(@CrossProfileContentSharingStrategy + int crossProfileContentSharingStrategy) { + mCrossProfileContentSharingStrategy = crossProfileContentSharingStrategy; + return this; + } + /** Builds a UserProperties object with *all* values populated. * @hide */ @@ -1253,7 +1353,8 @@ public final class UserProperties implements Parcelable { mCredentialShareableWithParent, mAuthAlwaysRequiredToDisableQuietMode, mDeleteAppWithParent, - mAlwaysVisible); + mAlwaysVisible, + mCrossProfileContentSharingStrategy); } } // end Builder @@ -1272,7 +1373,8 @@ public final class UserProperties implements Parcelable { boolean credentialShareableWithParent, boolean authAlwaysRequiredToDisableQuietMode, boolean deleteAppWithParent, - boolean alwaysVisible) { + boolean alwaysVisible, + @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) { mDefaultProperties = null; setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); @@ -1290,5 +1392,6 @@ public final class UserProperties implements Parcelable { authAlwaysRequiredToDisableQuietMode); setDeleteAppWithParent(deleteAppWithParent); setAlwaysVisible(alwaysVisible); + setCrossProfileContentSharingStrategy(crossProfileContentSharingStrategy); } } diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java index 4ef8cb780734..7f013b8df444 100644 --- a/services/core/java/com/android/server/pm/UserTypeFactory.java +++ b/services/core/java/com/android/server/pm/UserTypeFactory.java @@ -160,7 +160,9 @@ public final class UserTypeFactory { UserProperties.SHOW_IN_SHARING_SURFACES_WITH_PARENT) .setMediaSharedWithParent(true) .setCredentialShareableWithParent(true) - .setDeleteAppWithParent(true)); + .setDeleteAppWithParent(true) + .setCrossProfileContentSharingStrategy(UserProperties + .CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT)); } /** @@ -318,7 +320,9 @@ public final class UserTypeFactory { UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) - .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT)); + .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT) + .setCrossProfileContentSharingStrategy( + UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT)); } /** diff --git a/services/tests/servicestests/res/xml/usertypes_test_profile.xml b/services/tests/servicestests/res/xml/usertypes_test_profile.xml index e89199dc9278..9b047f2abff7 100644 --- a/services/tests/servicestests/res/xml/usertypes_test_profile.xml +++ b/services/tests/servicestests/res/xml/usertypes_test_profile.xml @@ -45,6 +45,7 @@ inheritDevicePolicy='450' deleteAppWithParent='false' alwaysVisible='true' + crossProfileContentSharingStrategy='0' /> </profile-type> <profile-type name='custom.test.1' max-allowed-per-parent='14' /> diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java index d70a4fd555ec..72cc969b5fb1 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java @@ -71,6 +71,7 @@ public class UserManagerServiceUserPropertiesTest { .setAuthAlwaysRequiredToDisableQuietMode(false) .setDeleteAppWithParent(false) .setAlwaysVisible(false) + .setCrossProfileContentSharingStrategy(0) .build(); final UserProperties actualProps = new UserProperties(defaultProps); actualProps.setShowInLauncher(14); @@ -86,6 +87,7 @@ public class UserManagerServiceUserPropertiesTest { actualProps.setAuthAlwaysRequiredToDisableQuietMode(true); actualProps.setDeleteAppWithParent(true); actualProps.setAlwaysVisible(true); + actualProps.setCrossProfileContentSharingStrategy(1); // Write the properties to xml. final ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -199,6 +201,8 @@ public class UserManagerServiceUserPropertiesTest { copy::isMediaSharedWithParent, true); assertEqualGetterOrThrows(orig::isCredentialShareableWithParent, copy::isCredentialShareableWithParent, true); + assertEqualGetterOrThrows(orig::getCrossProfileContentSharingStrategy, + copy::getCrossProfileContentSharingStrategy, true); } /** @@ -256,5 +260,7 @@ public class UserManagerServiceUserPropertiesTest { .isEqualTo(actual.isAuthAlwaysRequiredToDisableQuietMode()); assertThat(expected.getDeleteAppWithParent()).isEqualTo(actual.getDeleteAppWithParent()); assertThat(expected.getAlwaysVisible()).isEqualTo(actual.getAlwaysVisible()); + assertThat(expected.getCrossProfileContentSharingStrategy()) + .isEqualTo(actual.getCrossProfileContentSharingStrategy()); } } diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java index 77f693917574..d0ad57365942 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java @@ -29,7 +29,6 @@ import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; @@ -96,7 +95,8 @@ public class UserManagerServiceUserTypeTest { .setShowInQuietMode(30) .setInheritDevicePolicy(340) .setDeleteAppWithParent(true) - .setAlwaysVisible(true); + .setAlwaysVisible(true) + .setCrossProfileContentSharingStrategy(1); final UserTypeDetails type = new UserTypeDetails.Builder() .setName("a.name") @@ -175,6 +175,8 @@ public class UserManagerServiceUserTypeTest { .getInheritDevicePolicy()); assertTrue(type.getDefaultUserPropertiesReference().getDeleteAppWithParent()); assertTrue(type.getDefaultUserPropertiesReference().getAlwaysVisible()); + assertEquals(1, type.getDefaultUserPropertiesReference() + .getCrossProfileContentSharingStrategy()); assertEquals(23, type.getBadgeLabel(0)); assertEquals(24, type.getBadgeLabel(1)); @@ -231,6 +233,8 @@ public class UserManagerServiceUserTypeTest { assertEquals(UserProperties.SHOW_IN_LAUNCHER_SEPARATE, props.getShowInSharingSurfaces()); assertEquals(UserProperties.SHOW_IN_QUIET_MODE_PAUSED, props.getShowInQuietMode()); + assertEquals(UserProperties.CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION, + props.getCrossProfileContentSharingStrategy()); assertFalse(type.hasBadge()); } @@ -323,7 +327,8 @@ public class UserManagerServiceUserTypeTest { .setShowInSharingSurfaces(22) .setShowInQuietMode(24) .setDeleteAppWithParent(true) - .setAlwaysVisible(false); + .setAlwaysVisible(false) + .setCrossProfileContentSharingStrategy(1); final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); builders.put(userTypeAosp1, new UserTypeDetails.Builder() @@ -370,6 +375,8 @@ public class UserManagerServiceUserTypeTest { aospType.getDefaultUserPropertiesReference().getShowInQuietMode()); assertTrue(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent()); assertFalse(aospType.getDefaultUserPropertiesReference().getAlwaysVisible()); + assertEquals(1, aospType.getDefaultUserPropertiesReference() + .getCrossProfileContentSharingStrategy()); // userTypeAosp2 should be modified. aospType = builders.get(userTypeAosp2).createUserTypeDetails(); @@ -422,6 +429,8 @@ public class UserManagerServiceUserTypeTest { .getInheritDevicePolicy()); assertFalse(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent()); assertTrue(aospType.getDefaultUserPropertiesReference().getAlwaysVisible()); + assertEquals(0, aospType.getDefaultUserPropertiesReference() + .getCrossProfileContentSharingStrategy()); // userTypeOem1 should be created. UserTypeDetails.Builder customType = builders.get(userTypeOem1); 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 8933c6c56797..ced0bb5bc51c 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; import android.annotation.UserIdInt; import android.app.ActivityManager; @@ -219,6 +218,8 @@ public final class UserManagerTest { .isEqualTo(cloneUserProperties.isMediaSharedWithParent()); assertThat(typeProps.isCredentialShareableWithParent()) .isEqualTo(cloneUserProperties.isCredentialShareableWithParent()); + assertThat(typeProps.getCrossProfileContentSharingStrategy()) + .isEqualTo(cloneUserProperties.getCrossProfileContentSharingStrategy()); assertThrows(SecurityException.class, cloneUserProperties::getDeleteAppWithParent); assertThrows(SecurityException.class, cloneUserProperties::getAlwaysVisible); compareDrawables(mUserManager.getUserBadge(), @@ -338,6 +339,8 @@ public final class UserManagerTest { assertThat(typeProps.isAuthAlwaysRequiredToDisableQuietMode()) .isEqualTo(privateProfileUserProperties .isAuthAlwaysRequiredToDisableQuietMode()); + assertThat(typeProps.getCrossProfileContentSharingStrategy()) + .isEqualTo(privateProfileUserProperties.getCrossProfileContentSharingStrategy()); assertThrows(SecurityException.class, privateProfileUserProperties::getDeleteAppWithParent); compareDrawables(mUserManager.getUserBadge(), Resources.getSystem().getDrawable(userTypeDetails.getBadgePlain())); |