Merge "Adding user property for CrossProfileContentSharingStrategy." into main
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 9b11b50..c64f230 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4196,12 +4196,15 @@
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 7417137..3f2376d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1166,6 +1166,7 @@
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 56e8291..c401268 100644
--- a/core/java/android/content/pm/UserProperties.java
+++ b/core/java/android/content/pm/UserProperties.java
@@ -69,6 +69,9 @@
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 @@
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 @@
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 @@
*/
@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 @@
setCredentialShareableWithParent(orig.isCredentialShareableWithParent());
setShowInQuietMode(orig.getShowInQuietMode());
setShowInSharingSurfaces(orig.getShowInSharingSurfaces());
+ setCrossProfileContentSharingStrategy(orig.getCrossProfileContentSharingStrategy());
}
/**
@@ -776,8 +821,7 @@
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 @@
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 @@
}
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 @@
+ isAuthAlwaysRequiredToDisableQuietMode()
+ ", mDeleteAppWithParent=" + getDeleteAppWithParent()
+ ", mAlwaysVisible=" + getAlwaysVisible()
+ + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy()
+ "}";
}
@@ -856,6 +931,8 @@
+ isAuthAlwaysRequiredToDisableQuietMode());
pw.println(prefix + " mDeleteAppWithParent=" + getDeleteAppWithParent());
pw.println(prefix + " mAlwaysVisible=" + getAlwaysVisible());
+ pw.println(prefix + " mCrossProfileContentSharingStrategy="
+ + getCrossProfileContentSharingStrategy());
}
/**
@@ -934,6 +1011,8 @@
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 @@
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 @@
dest.writeBoolean(mAuthAlwaysRequiredToDisableQuietMode);
dest.writeBoolean(mDeleteAppWithParent);
dest.writeBoolean(mAlwaysVisible);
+ dest.writeInt(mCrossProfileContentSharingStrategy);
}
/**
@@ -1054,6 +1138,7 @@
mAuthAlwaysRequiredToDisableQuietMode = source.readBoolean();
mDeleteAppWithParent = source.readBoolean();
mAlwaysVisible = source.readBoolean();
+ mCrossProfileContentSharingStrategy = source.readInt();
}
@Override
@@ -1100,6 +1185,8 @@
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 @@
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 @@
mCredentialShareableWithParent,
mAuthAlwaysRequiredToDisableQuietMode,
mDeleteAppWithParent,
- mAlwaysVisible);
+ mAlwaysVisible,
+ mCrossProfileContentSharingStrategy);
}
} // end Builder
@@ -1272,7 +1373,8 @@
boolean credentialShareableWithParent,
boolean authAlwaysRequiredToDisableQuietMode,
boolean deleteAppWithParent,
- boolean alwaysVisible) {
+ boolean alwaysVisible,
+ @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) {
mDefaultProperties = null;
setShowInLauncher(showInLauncher);
setStartWithParent(startWithParent);
@@ -1290,5 +1392,6 @@
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 4ef8cb7..7f013b8 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 @@
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 @@
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 e89199d..9b047f2 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 d70a4fd..72cc969 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 @@
.setAuthAlwaysRequiredToDisableQuietMode(false)
.setDeleteAppWithParent(false)
.setAlwaysVisible(false)
+ .setCrossProfileContentSharingStrategy(0)
.build();
final UserProperties actualProps = new UserProperties(defaultProps);
actualProps.setShowInLauncher(14);
@@ -86,6 +87,7 @@
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 @@
copy::isMediaSharedWithParent, true);
assertEqualGetterOrThrows(orig::isCredentialShareableWithParent,
copy::isCredentialShareableWithParent, true);
+ assertEqualGetterOrThrows(orig::getCrossProfileContentSharingStrategy,
+ copy::getCrossProfileContentSharingStrategy, true);
}
/**
@@ -256,5 +260,7 @@
.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 77f6939..d0ad573 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 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 @@
.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 @@
.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 @@
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 @@
.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 @@
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 @@
.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 8933c6c..ced0bb5 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.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 @@
.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 @@
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()));