Loading core/java/android/content/pm/UserProperties.java +96 −3 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ public final class UserProperties implements Parcelable { "updateCrossProfileIntentFiltersOnOTA"; private static final String ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = "crossProfileIntentFilterAccessControl"; private static final String ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = "crossProfileIntentResolutionStrategy"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { Loading @@ -59,7 +61,8 @@ public final class UserProperties implements Parcelable { INDEX_INHERIT_DEVICE_POLICY, INDEX_USE_PARENTS_CONTACTS, INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA, INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { Loading @@ -71,6 +74,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_USE_PARENTS_CONTACTS = 4; private static final int INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA = 5; private static final int INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = 6; private static final int INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = 7; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; Loading Loading @@ -218,6 +222,39 @@ public final class UserProperties implements Parcelable { */ public static final int CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM_ADD_ONLY = 20; /** * Possible values for cross profile intent resolution strategy. * * @hide */ @IntDef(prefix = {"CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_"}, value = { CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT, CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING }) @Retention(RetentionPolicy.SOURCE) public @interface CrossProfileIntentResolutionStrategy { } /** * Signifies to use {@link DefaultCrossProfileResolver} strategy, which * check if it needs to skip the initiating profile, resolves intent in target profile. * {@link DefaultCrossProfileResolver} also filters the {@link ResolveInfo} after intent * resolution based on their domain approval level * * @hide */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT = 0; /** * Signifies that there is no need to filter {@link ResolveInfo} after cross profile intent * resolution across. This strategy is for profile acting transparent to end-user and resolves * all allowed intent without giving any profile priority. * * @hide */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING = 1; /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given * default properties, which it uses for any property not subsequently set. Loading Loading @@ -255,6 +292,7 @@ public final class UserProperties implements Parcelable { setUpdateCrossProfileIntentFiltersOnOTA(orig.getUpdateCrossProfileIntentFiltersOnOTA()); setCrossProfileIntentFilterAccessControl( orig.getCrossProfileIntentFilterAccessControl()); setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy()); } if (hasManagePermission) { // Add items that require MANAGE_USERS or stronger. Loading Loading @@ -466,6 +504,36 @@ 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}. * @return user's {@link CrossProfileIntentResolutionStrategy}. * * @hide */ public @CrossProfileIntentResolutionStrategy int getCrossProfileIntentResolutionStrategy() { if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) { return mCrossProfileIntentResolutionStrategy; } if (mDefaultProperties != null) { return mDefaultProperties.mCrossProfileIntentResolutionStrategy; } throw new SecurityException("You don't have permission to query " + "crossProfileIntentResolutionStrategy"); } /** * Sets {@link CrossProfileIntentResolutionStrategy} for the user. * @param val resolution strategy for user * @hide */ public void setCrossProfileIntentResolutionStrategy( @CrossProfileIntentResolutionStrategy int val) { this.mCrossProfileIntentResolutionStrategy = val; setPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY); } private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy; @Override public String toString() { // Please print in increasing order of PropertyIndex. Loading @@ -480,6 +548,8 @@ public final class UserProperties implements Parcelable { + getUpdateCrossProfileIntentFiltersOnOTA() + ", mCrossProfileIntentFilterAccessControl=" + getCrossProfileIntentFilterAccessControl() + ", mCrossProfileIntentResolutionStrategy=" + getCrossProfileIntentResolutionStrategy() + "}"; } Loading @@ -500,6 +570,8 @@ public final class UserProperties implements Parcelable { + getUpdateCrossProfileIntentFiltersOnOTA()); pw.println(prefix + " mCrossProfileIntentFilterAccessControl=" + getCrossProfileIntentFilterAccessControl()); pw.println(prefix + " mCrossProfileIntentResolutionStrategy=" + getCrossProfileIntentResolutionStrategy()); } /** Loading Loading @@ -554,6 +626,9 @@ public final class UserProperties implements Parcelable { case ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL: setCrossProfileIntentFilterAccessControl(parser.getAttributeInt(i)); break; case ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY: setCrossProfileIntentResolutionStrategy(parser.getAttributeInt(i)); break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } Loading Loading @@ -597,6 +672,10 @@ public final class UserProperties implements Parcelable { serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, mCrossProfileIntentFilterAccessControl); } if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) { serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY, mCrossProfileIntentResolutionStrategy); } } // For use only with an object that has already had any permission-lacking fields stripped out. Loading @@ -610,6 +689,7 @@ public final class UserProperties implements Parcelable { dest.writeBoolean(mUseParentsContacts); dest.writeBoolean(mUpdateCrossProfileIntentFiltersOnOTA); dest.writeInt(mCrossProfileIntentFilterAccessControl); dest.writeInt(mCrossProfileIntentResolutionStrategy); } /** Loading @@ -627,6 +707,7 @@ public final class UserProperties implements Parcelable { mUseParentsContacts = source.readBoolean(); mUpdateCrossProfileIntentFiltersOnOTA = source.readBoolean(); mCrossProfileIntentFilterAccessControl = source.readInt(); mCrossProfileIntentResolutionStrategy = source.readInt(); } @Override Loading Loading @@ -660,6 +741,8 @@ public final class UserProperties implements Parcelable { private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl = CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL; private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy = CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT; public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) { mShowInLauncher = showInLauncher; Loading Loading @@ -704,6 +787,13 @@ public final class UserProperties implements Parcelable { return this; } /** Sets the value for {@link #mCrossProfileIntentResolutionStrategy} */ public Builder setCrossProfileIntentResolutionStrategy(@CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy) { mCrossProfileIntentResolutionStrategy = crossProfileIntentResolutionStrategy; return this; } /** Builds a UserProperties object with *all* values populated. */ public UserProperties build() { return new UserProperties( Loading @@ -713,7 +803,8 @@ public final class UserProperties implements Parcelable { mInheritDevicePolicy, mUseParentsContacts, mUpdateCrossProfileIntentFiltersOnOTA, mCrossProfileIntentFilterAccessControl); mCrossProfileIntentFilterAccessControl, mCrossProfileIntentResolutionStrategy); } } // end Builder Loading @@ -724,7 +815,8 @@ public final class UserProperties implements Parcelable { @ShowInSettings int showInSettings, @InheritDevicePolicy int inheritDevicePolicy, boolean useParentsContacts, boolean updateCrossProfileIntentFiltersOnOTA, @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl) { @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl, @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy) { mDefaultProperties = null; setShowInLauncher(showInLauncher); Loading @@ -734,5 +826,6 @@ public final class UserProperties implements Parcelable { setUseParentsContacts(useParentsContacts); setUpdateCrossProfileIntentFiltersOnOTA(updateCrossProfileIntentFiltersOnOTA); setCrossProfileIntentFilterAccessControl(crossProfileIntentFilterAccessControl); setCrossProfileIntentResolutionStrategy(crossProfileIntentResolutionStrategy); } } services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +40 −18 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.pm.UserProperties; import android.os.Process; import android.text.TextUtils; import android.util.Pair; Loading Loading @@ -147,8 +148,6 @@ public class CrossProfileIntentResolverEngine { return crossProfileDomainInfos; } UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); // Grouping the CrossProfileIntentFilters based on targerId SparseArray<List<CrossProfileIntentFilter>> crossProfileIntentFiltersByUser = new SparseArray<>(); Loading Loading @@ -183,11 +182,9 @@ public class CrossProfileIntentResolverEngine { continue; } UserInfo targetUserInfo = mUserManagerInternal.getUserInfo(targetUserId); // Choosing strategy based on source and target user CrossProfileResolver crossProfileResolver = chooseCrossProfileResolver(computer, userInfo, targetUserInfo); chooseCrossProfileResolver(computer, userId, targetUserId); /* If {@link CrossProfileResolver} is available for source,target pair we will call it to Loading Loading @@ -234,23 +231,21 @@ public class CrossProfileIntentResolverEngine { /** * Returns {@link CrossProfileResolver} strategy based on source and target user * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi} * @param sourceUserInfo source user * @param targetUserInfo target user * @param sourceUserId source user * @param targetUserId target user * @return {@code CrossProfileResolver} which has value if source and target have * strategy configured otherwise null. */ @SuppressWarnings("unused") private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer, UserInfo sourceUserInfo, UserInfo targetUserInfo) { //todo change isCloneProfile to user properties b/241532322 @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { /** * If source or target user is clone profile, using {@link CloneProfileResolver} * We would allow CloneProfileResolver only if flag * SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE is enabled * If source or target user is clone profile, using {@link NoFilteringResolver} * We would return NoFilteringResolver only if it is allowed(feature flag is set). */ if (sourceUserInfo.isCloneProfile() || targetUserInfo.isCloneProfile()) { if (CloneProfileResolver.isIntentRedirectionForCloneProfileAllowed()) { return new CloneProfileResolver(computer.getComponentResolver(), if (shouldUseNoFilteringResolver(sourceUserId, targetUserId)) { if (NoFilteringResolver.isIntentRedirectionAllowed()) { return new NoFilteringResolver(computer.getComponentResolver(), mUserManager); } else { return null; Loading Loading @@ -624,7 +619,6 @@ public class CrossProfileIntentResolverEngine { categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) { List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); UserInfo sourceUserInfo = mUserManagerInternal.getUserInfo(sourceUserId); for (int index = 0; index < categorizeResolveInfoByTargetUser.size(); index++) { Loading @@ -634,8 +628,8 @@ public class CrossProfileIntentResolverEngine { } else { // finding cross profile strategy based on source and target user CrossProfileResolver crossProfileIntentResolver = chooseCrossProfileResolver(computer, sourceUserInfo, mUserManagerInternal .getUserInfo(categorizeResolveInfoByTargetUser.keyAt(index))); chooseCrossProfileResolver(computer, sourceUserId, categorizeResolveInfoByTargetUser.keyAt(index)); // if strategy is available call it and add its filtered results if (crossProfileIntentResolver != null) { crossProfileDomainInfos.addAll(crossProfileIntentResolver Loading Loading @@ -678,4 +672,32 @@ public class CrossProfileIntentResolverEngine { && crossProfileDomainInfos.get(0).mResolveInfo != null && crossProfileDomainInfos.get(0).mResolveInfo.priority >= 0; } /** * Deciding if we need to user {@link NoFilteringResolver} based on source and target user * @param sourceUserId id of initiating user * @param targetUserId id of cross profile linked user * @return true if {@link NoFilteringResolver} is applicable in this case. */ private boolean shouldUseNoFilteringResolver(@UserIdInt int sourceUserId, @UserIdInt int targetUserId) { return isNoFilteringPropertyConfiguredForUser(sourceUserId) || isNoFilteringPropertyConfiguredForUser(targetUserId); } /** * Check if configure property for cross profile intent resolution strategy for user is * {@link UserProperties#CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING} * @param userId id of user to check for property * @return true if user have property set to * {@link UserProperties#CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING} */ private boolean isNoFilteringPropertyConfiguredForUser(@UserIdInt int userId) { if (!mUserManager.isProfile(userId)) return false; UserProperties userProperties = mUserManagerInternal.getUserProperties(userId); if (userProperties == null) return false; return userProperties.getCrossProfileIntentResolutionStrategy() == UserProperties.CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING; } } services/core/java/com/android/server/pm/CloneProfileResolver.java→services/core/java/com/android/server/pm/NoFilteringResolver.java +9 −8 Original line number Diff line number Diff line Loading @@ -30,9 +30,10 @@ import java.util.List; import java.util.function.Function; /** * Cross Profile intent resolution strategy used for and to clone profile. * Intent resolution strategy used when no filtering is required. As of now, the known use-case is * clone profile. */ public class CloneProfileResolver extends CrossProfileResolver { public class NoFilteringResolver extends CrossProfileResolver { /** * Feature flag to allow/restrict intent redirection from/to clone profile. Loading @@ -48,7 +49,7 @@ public class CloneProfileResolver extends CrossProfileResolver { * Returns true if intent redirection for clone profile feature flag is set * @return value of flag allow_intent_redirection_for_clone_profile */ public static boolean isIntentRedirectionForCloneProfileAllowed() { public static boolean isIntentRedirectionAllowed() { final long token = Binder.clearCallingIdentity(); try { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APP_CLONING, Loading @@ -58,13 +59,13 @@ public class CloneProfileResolver extends CrossProfileResolver { } } public CloneProfileResolver(ComponentResolverApi componentResolver, public NoFilteringResolver(ComponentResolverApi componentResolver, UserManagerService userManagerService) { super(componentResolver, userManagerService); } /** * This is resolution strategy for Clone Profile. * This is resolution strategy for when no filtering is required. * In case of clone profile, the profile is supposed to be transparent to end user. To end user * clone and owner profile should be part of same user space. Hence, the resolution strategy * would resolve intent in both profile and return combined result without any filtering of the Loading Loading @@ -105,8 +106,8 @@ public class CloneProfileResolver extends CrossProfileResolver { } /** * As clone and owner profile are going to be part of the same userspace, we need no filtering * out of any clone profile's result * In case of Clone profile, the clone and owner profile are going to be part of the same * userspace, we need no filtering out of any clone profile's result. * @param intent request * @param crossProfileDomainInfos resolved in target user * @param flags for intent resolution Loading @@ -119,7 +120,7 @@ public class CloneProfileResolver extends CrossProfileResolver { public List<CrossProfileDomainInfo> filterResolveInfoWithDomainPreferredActivity(Intent intent, List<CrossProfileDomainInfo> crossProfileDomainInfos, long flags, int sourceUserId, int targetUserId, int highestApprovalLevel) { // no filtering for clone profile // no filtering return crossProfileDomainInfos; } } services/core/java/com/android/server/pm/UserTypeFactory.java +3 −1 Original line number Diff line number Diff line Loading @@ -133,7 +133,9 @@ public final class UserTypeFactory { .setUseParentsContacts(true) .setUpdateCrossProfileIntentFiltersOnOTA(true) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM)); UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setCrossProfileIntentResolutionStrategy(UserProperties .CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING)); } /** Loading services/tests/servicestests/res/xml/usertypes_test_profile.xml +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ startWithParent='false' useParentsContacts='false' crossProfileIntentFilterAccessControl='20' crossProfileIntentResolutionStrategy='0' /> </profile-type> <profile-type name='custom.test.1' max-allowed-per-parent='14' /> Loading Loading
core/java/android/content/pm/UserProperties.java +96 −3 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ public final class UserProperties implements Parcelable { "updateCrossProfileIntentFiltersOnOTA"; private static final String ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = "crossProfileIntentFilterAccessControl"; private static final String ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = "crossProfileIntentResolutionStrategy"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { Loading @@ -59,7 +61,8 @@ public final class UserProperties implements Parcelable { INDEX_INHERIT_DEVICE_POLICY, INDEX_USE_PARENTS_CONTACTS, INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA, INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { Loading @@ -71,6 +74,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_USE_PARENTS_CONTACTS = 4; private static final int INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA = 5; private static final int INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL = 6; private static final int INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = 7; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; Loading Loading @@ -218,6 +222,39 @@ public final class UserProperties implements Parcelable { */ public static final int CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM_ADD_ONLY = 20; /** * Possible values for cross profile intent resolution strategy. * * @hide */ @IntDef(prefix = {"CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_"}, value = { CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT, CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING }) @Retention(RetentionPolicy.SOURCE) public @interface CrossProfileIntentResolutionStrategy { } /** * Signifies to use {@link DefaultCrossProfileResolver} strategy, which * check if it needs to skip the initiating profile, resolves intent in target profile. * {@link DefaultCrossProfileResolver} also filters the {@link ResolveInfo} after intent * resolution based on their domain approval level * * @hide */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT = 0; /** * Signifies that there is no need to filter {@link ResolveInfo} after cross profile intent * resolution across. This strategy is for profile acting transparent to end-user and resolves * all allowed intent without giving any profile priority. * * @hide */ public static final int CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING = 1; /** * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given * default properties, which it uses for any property not subsequently set. Loading Loading @@ -255,6 +292,7 @@ public final class UserProperties implements Parcelable { setUpdateCrossProfileIntentFiltersOnOTA(orig.getUpdateCrossProfileIntentFiltersOnOTA()); setCrossProfileIntentFilterAccessControl( orig.getCrossProfileIntentFilterAccessControl()); setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy()); } if (hasManagePermission) { // Add items that require MANAGE_USERS or stronger. Loading Loading @@ -466,6 +504,36 @@ 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}. * @return user's {@link CrossProfileIntentResolutionStrategy}. * * @hide */ public @CrossProfileIntentResolutionStrategy int getCrossProfileIntentResolutionStrategy() { if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) { return mCrossProfileIntentResolutionStrategy; } if (mDefaultProperties != null) { return mDefaultProperties.mCrossProfileIntentResolutionStrategy; } throw new SecurityException("You don't have permission to query " + "crossProfileIntentResolutionStrategy"); } /** * Sets {@link CrossProfileIntentResolutionStrategy} for the user. * @param val resolution strategy for user * @hide */ public void setCrossProfileIntentResolutionStrategy( @CrossProfileIntentResolutionStrategy int val) { this.mCrossProfileIntentResolutionStrategy = val; setPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY); } private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy; @Override public String toString() { // Please print in increasing order of PropertyIndex. Loading @@ -480,6 +548,8 @@ public final class UserProperties implements Parcelable { + getUpdateCrossProfileIntentFiltersOnOTA() + ", mCrossProfileIntentFilterAccessControl=" + getCrossProfileIntentFilterAccessControl() + ", mCrossProfileIntentResolutionStrategy=" + getCrossProfileIntentResolutionStrategy() + "}"; } Loading @@ -500,6 +570,8 @@ public final class UserProperties implements Parcelable { + getUpdateCrossProfileIntentFiltersOnOTA()); pw.println(prefix + " mCrossProfileIntentFilterAccessControl=" + getCrossProfileIntentFilterAccessControl()); pw.println(prefix + " mCrossProfileIntentResolutionStrategy=" + getCrossProfileIntentResolutionStrategy()); } /** Loading Loading @@ -554,6 +626,9 @@ public final class UserProperties implements Parcelable { case ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL: setCrossProfileIntentFilterAccessControl(parser.getAttributeInt(i)); break; case ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY: setCrossProfileIntentResolutionStrategy(parser.getAttributeInt(i)); break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } Loading Loading @@ -597,6 +672,10 @@ public final class UserProperties implements Parcelable { serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, mCrossProfileIntentFilterAccessControl); } if (isPresent(INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY)) { serializer.attributeInt(null, ATTR_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY, mCrossProfileIntentResolutionStrategy); } } // For use only with an object that has already had any permission-lacking fields stripped out. Loading @@ -610,6 +689,7 @@ public final class UserProperties implements Parcelable { dest.writeBoolean(mUseParentsContacts); dest.writeBoolean(mUpdateCrossProfileIntentFiltersOnOTA); dest.writeInt(mCrossProfileIntentFilterAccessControl); dest.writeInt(mCrossProfileIntentResolutionStrategy); } /** Loading @@ -627,6 +707,7 @@ public final class UserProperties implements Parcelable { mUseParentsContacts = source.readBoolean(); mUpdateCrossProfileIntentFiltersOnOTA = source.readBoolean(); mCrossProfileIntentFilterAccessControl = source.readInt(); mCrossProfileIntentResolutionStrategy = source.readInt(); } @Override Loading Loading @@ -660,6 +741,8 @@ public final class UserProperties implements Parcelable { private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl = CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL; private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy = CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT; public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) { mShowInLauncher = showInLauncher; Loading Loading @@ -704,6 +787,13 @@ public final class UserProperties implements Parcelable { return this; } /** Sets the value for {@link #mCrossProfileIntentResolutionStrategy} */ public Builder setCrossProfileIntentResolutionStrategy(@CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy) { mCrossProfileIntentResolutionStrategy = crossProfileIntentResolutionStrategy; return this; } /** Builds a UserProperties object with *all* values populated. */ public UserProperties build() { return new UserProperties( Loading @@ -713,7 +803,8 @@ public final class UserProperties implements Parcelable { mInheritDevicePolicy, mUseParentsContacts, mUpdateCrossProfileIntentFiltersOnOTA, mCrossProfileIntentFilterAccessControl); mCrossProfileIntentFilterAccessControl, mCrossProfileIntentResolutionStrategy); } } // end Builder Loading @@ -724,7 +815,8 @@ public final class UserProperties implements Parcelable { @ShowInSettings int showInSettings, @InheritDevicePolicy int inheritDevicePolicy, boolean useParentsContacts, boolean updateCrossProfileIntentFiltersOnOTA, @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl) { @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl, @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy) { mDefaultProperties = null; setShowInLauncher(showInLauncher); Loading @@ -734,5 +826,6 @@ public final class UserProperties implements Parcelable { setUseParentsContacts(useParentsContacts); setUpdateCrossProfileIntentFiltersOnOTA(updateCrossProfileIntentFiltersOnOTA); setCrossProfileIntentFilterAccessControl(crossProfileIntentFilterAccessControl); setCrossProfileIntentResolutionStrategy(crossProfileIntentResolutionStrategy); } }
services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +40 −18 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.pm.UserProperties; import android.os.Process; import android.text.TextUtils; import android.util.Pair; Loading Loading @@ -147,8 +148,6 @@ public class CrossProfileIntentResolverEngine { return crossProfileDomainInfos; } UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); // Grouping the CrossProfileIntentFilters based on targerId SparseArray<List<CrossProfileIntentFilter>> crossProfileIntentFiltersByUser = new SparseArray<>(); Loading Loading @@ -183,11 +182,9 @@ public class CrossProfileIntentResolverEngine { continue; } UserInfo targetUserInfo = mUserManagerInternal.getUserInfo(targetUserId); // Choosing strategy based on source and target user CrossProfileResolver crossProfileResolver = chooseCrossProfileResolver(computer, userInfo, targetUserInfo); chooseCrossProfileResolver(computer, userId, targetUserId); /* If {@link CrossProfileResolver} is available for source,target pair we will call it to Loading Loading @@ -234,23 +231,21 @@ public class CrossProfileIntentResolverEngine { /** * Returns {@link CrossProfileResolver} strategy based on source and target user * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi} * @param sourceUserInfo source user * @param targetUserInfo target user * @param sourceUserId source user * @param targetUserId target user * @return {@code CrossProfileResolver} which has value if source and target have * strategy configured otherwise null. */ @SuppressWarnings("unused") private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer, UserInfo sourceUserInfo, UserInfo targetUserInfo) { //todo change isCloneProfile to user properties b/241532322 @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { /** * If source or target user is clone profile, using {@link CloneProfileResolver} * We would allow CloneProfileResolver only if flag * SETTINGS_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE is enabled * If source or target user is clone profile, using {@link NoFilteringResolver} * We would return NoFilteringResolver only if it is allowed(feature flag is set). */ if (sourceUserInfo.isCloneProfile() || targetUserInfo.isCloneProfile()) { if (CloneProfileResolver.isIntentRedirectionForCloneProfileAllowed()) { return new CloneProfileResolver(computer.getComponentResolver(), if (shouldUseNoFilteringResolver(sourceUserId, targetUserId)) { if (NoFilteringResolver.isIntentRedirectionAllowed()) { return new NoFilteringResolver(computer.getComponentResolver(), mUserManager); } else { return null; Loading Loading @@ -624,7 +619,6 @@ public class CrossProfileIntentResolverEngine { categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) { List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); UserInfo sourceUserInfo = mUserManagerInternal.getUserInfo(sourceUserId); for (int index = 0; index < categorizeResolveInfoByTargetUser.size(); index++) { Loading @@ -634,8 +628,8 @@ public class CrossProfileIntentResolverEngine { } else { // finding cross profile strategy based on source and target user CrossProfileResolver crossProfileIntentResolver = chooseCrossProfileResolver(computer, sourceUserInfo, mUserManagerInternal .getUserInfo(categorizeResolveInfoByTargetUser.keyAt(index))); chooseCrossProfileResolver(computer, sourceUserId, categorizeResolveInfoByTargetUser.keyAt(index)); // if strategy is available call it and add its filtered results if (crossProfileIntentResolver != null) { crossProfileDomainInfos.addAll(crossProfileIntentResolver Loading Loading @@ -678,4 +672,32 @@ public class CrossProfileIntentResolverEngine { && crossProfileDomainInfos.get(0).mResolveInfo != null && crossProfileDomainInfos.get(0).mResolveInfo.priority >= 0; } /** * Deciding if we need to user {@link NoFilteringResolver} based on source and target user * @param sourceUserId id of initiating user * @param targetUserId id of cross profile linked user * @return true if {@link NoFilteringResolver} is applicable in this case. */ private boolean shouldUseNoFilteringResolver(@UserIdInt int sourceUserId, @UserIdInt int targetUserId) { return isNoFilteringPropertyConfiguredForUser(sourceUserId) || isNoFilteringPropertyConfiguredForUser(targetUserId); } /** * Check if configure property for cross profile intent resolution strategy for user is * {@link UserProperties#CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING} * @param userId id of user to check for property * @return true if user have property set to * {@link UserProperties#CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING} */ private boolean isNoFilteringPropertyConfiguredForUser(@UserIdInt int userId) { if (!mUserManager.isProfile(userId)) return false; UserProperties userProperties = mUserManagerInternal.getUserProperties(userId); if (userProperties == null) return false; return userProperties.getCrossProfileIntentResolutionStrategy() == UserProperties.CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING; } }
services/core/java/com/android/server/pm/CloneProfileResolver.java→services/core/java/com/android/server/pm/NoFilteringResolver.java +9 −8 Original line number Diff line number Diff line Loading @@ -30,9 +30,10 @@ import java.util.List; import java.util.function.Function; /** * Cross Profile intent resolution strategy used for and to clone profile. * Intent resolution strategy used when no filtering is required. As of now, the known use-case is * clone profile. */ public class CloneProfileResolver extends CrossProfileResolver { public class NoFilteringResolver extends CrossProfileResolver { /** * Feature flag to allow/restrict intent redirection from/to clone profile. Loading @@ -48,7 +49,7 @@ public class CloneProfileResolver extends CrossProfileResolver { * Returns true if intent redirection for clone profile feature flag is set * @return value of flag allow_intent_redirection_for_clone_profile */ public static boolean isIntentRedirectionForCloneProfileAllowed() { public static boolean isIntentRedirectionAllowed() { final long token = Binder.clearCallingIdentity(); try { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APP_CLONING, Loading @@ -58,13 +59,13 @@ public class CloneProfileResolver extends CrossProfileResolver { } } public CloneProfileResolver(ComponentResolverApi componentResolver, public NoFilteringResolver(ComponentResolverApi componentResolver, UserManagerService userManagerService) { super(componentResolver, userManagerService); } /** * This is resolution strategy for Clone Profile. * This is resolution strategy for when no filtering is required. * In case of clone profile, the profile is supposed to be transparent to end user. To end user * clone and owner profile should be part of same user space. Hence, the resolution strategy * would resolve intent in both profile and return combined result without any filtering of the Loading Loading @@ -105,8 +106,8 @@ public class CloneProfileResolver extends CrossProfileResolver { } /** * As clone and owner profile are going to be part of the same userspace, we need no filtering * out of any clone profile's result * In case of Clone profile, the clone and owner profile are going to be part of the same * userspace, we need no filtering out of any clone profile's result. * @param intent request * @param crossProfileDomainInfos resolved in target user * @param flags for intent resolution Loading @@ -119,7 +120,7 @@ public class CloneProfileResolver extends CrossProfileResolver { public List<CrossProfileDomainInfo> filterResolveInfoWithDomainPreferredActivity(Intent intent, List<CrossProfileDomainInfo> crossProfileDomainInfos, long flags, int sourceUserId, int targetUserId, int highestApprovalLevel) { // no filtering for clone profile // no filtering return crossProfileDomainInfos; } }
services/core/java/com/android/server/pm/UserTypeFactory.java +3 −1 Original line number Diff line number Diff line Loading @@ -133,7 +133,9 @@ public final class UserTypeFactory { .setUseParentsContacts(true) .setUpdateCrossProfileIntentFiltersOnOTA(true) .setCrossProfileIntentFilterAccessControl( UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM)); UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM) .setCrossProfileIntentResolutionStrategy(UserProperties .CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING)); } /** Loading
services/tests/servicestests/res/xml/usertypes_test_profile.xml +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ startWithParent='false' useParentsContacts='false' crossProfileIntentFilterAccessControl='20' crossProfileIntentResolutionStrategy='0' /> </profile-type> <profile-type name='custom.test.1' max-allowed-per-parent='14' /> Loading