Loading services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +132 −135 Original line number Diff line number Diff line Loading @@ -36,18 +36,15 @@ import android.util.FeatureFlagUtils; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.server.LocalServices; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationUtils; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.function.Function; Loading @@ -62,6 +59,7 @@ public class CrossProfileIntentResolverEngine { private final DomainVerificationManagerInternal mDomainVerificationManager; private final DefaultAppProvider mDefaultAppProvider; private final Context mContext; private final UserManagerInternal mUserManagerInternal; public CrossProfileIntentResolverEngine(UserManagerService userManager, DomainVerificationManagerInternal domainVerificationManager, Loading @@ -70,6 +68,7 @@ public class CrossProfileIntentResolverEngine { mDomainVerificationManager = domainVerificationManager; mDefaultAppProvider = defaultAppProvider; mContext = context; mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); } /** Loading @@ -92,14 +91,14 @@ public class CrossProfileIntentResolverEngine { String resolvedType, int userId, long flags, String pkgName, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction) { return resolveIntentInternal(computer, intent, resolvedType, userId, flags, pkgName, hasNonNegativePriorityResult, pkgSettingFunction); return resolveIntentInternal(computer, intent, resolvedType, userId, userId, flags, pkgName, hasNonNegativePriorityResult, pkgSettingFunction, null); } /** * Resolves intent in directly linked profiles and return list of {@link CrossProfileDomainInfo} * which contains {@link ResolveInfo}. This would also iteratively call profiles not directly * linked using Breadth First Search. * which contains {@link ResolveInfo}. This would also recursively call profiles not directly * linked using Depth First Search. * * It first finds {@link CrossProfileIntentFilter} configured in current profile to find list of * target user profiles that can serve current intent request. It uses corresponding strategy Loading @@ -108,51 +107,48 @@ public class CrossProfileIntentResolverEngine { * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi} * @param intent request * @param resolvedType the MIME data type of intent request * @param userId source user for which intent request is called * @param sourceUserId source user for which intent request is called * @param userId current user for cross profile resolution * @param flags used for intent resolution * @param pkgName the application package name this Intent is limited to. * @param hasNonNegativePriorityResult signifies if current profile have any non-negative(active * and valid) ResolveInfo in current profile. * @param pkgSettingFunction function to find PackageStateInternal for given package * @param visitedUserIds users for which we have already performed resolution * @return list of {@link CrossProfileDomainInfo} from linked profiles. */ private List<CrossProfileDomainInfo> resolveIntentInternal(@NonNull Computer computer, Intent intent, String resolvedType, int userId, long flags, String pkgName, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction) { Queue<Integer> pendingUsers = new ArrayDeque<>(); Set<Integer> visitedUserIds = new HashSet<>(); SparseBooleanArray hasNonNegativePriorityResultFromParent = new SparseBooleanArray(); visitedUserIds.add(userId); pendingUsers.add(userId); hasNonNegativePriorityResultFromParent.put(userId, hasNonNegativePriorityResult); UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); Intent intent, String resolvedType, int sourceUserId, int userId, long flags, String pkgName, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction, Set<Integer> visitedUserIds) { if (visitedUserIds != null) visitedUserIds.add(userId); List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); while (!pendingUsers.isEmpty()) { int currentUserId = pendingUsers.poll(); List<CrossProfileIntentFilter> matchingFilters = computer.getMatchingCrossProfileIntentFilters(intent, resolvedType, currentUserId); userId); if (matchingFilters == null || matchingFilters.isEmpty()) { /** if intent is web intent, checking if parent profile should handle the intent * even if there is no matching filter. The configuration is based on user profile * restriction android.os.UserManager#ALLOW_PARENT_PROFILE_APP_LINKING **/ if (currentUserId == userId && intent.hasWebURI()) { UserInfo parent = computer.getProfileParent(currentUserId); if (sourceUserId == userId && intent.hasWebURI()) { UserInfo parent = computer.getProfileParent(userId); if (parent != null) { CrossProfileDomainInfo generalizedCrossProfileDomainInfo = computer .getCrossProfileDomainPreferredLpr(intent, resolvedType, flags, currentUserId, parent.id); userId, parent.id); if (generalizedCrossProfileDomainInfo != null) { crossProfileDomainInfos.add(generalizedCrossProfileDomainInfo); } } } continue; return crossProfileDomainInfos; } UserInfo sourceUserInfo = umInternal.getUserInfo(currentUserId); UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); // Grouping the CrossProfileIntentFilters based on targerId SparseArray<List<CrossProfileIntentFilter>> crossProfileIntentFiltersByUser = Loading @@ -170,6 +166,11 @@ public class CrossProfileIntentResolverEngine { .add(crossProfileIntentFilter); } if (visitedUserIds == null) { visitedUserIds = new HashSet<>(); visitedUserIds.add(userId); } /* For each target user, we would call their corresponding strategy {@link CrossProfileResolver} to resolve intent in corresponding user Loading @@ -183,11 +184,11 @@ public class CrossProfileIntentResolverEngine { continue; } UserInfo targetUserInfo = umInternal.getUserInfo(targetUserId); UserInfo targetUserInfo = mUserManagerInternal.getUserInfo(targetUserId); // Choosing strategy based on source and target user CrossProfileResolver crossProfileResolver = chooseCrossProfileResolver(computer, sourceUserInfo, targetUserInfo); chooseCrossProfileResolver(computer, userInfo, targetUserInfo); /* If {@link CrossProfileResolver} is available for source,target pair we will call it to Loading @@ -195,15 +196,12 @@ public class CrossProfileIntentResolverEngine { */ if (crossProfileResolver != null) { List<CrossProfileDomainInfo> crossProfileInfos = crossProfileResolver .resolveIntent(computer, intent, resolvedType, currentUserId, .resolveIntent(computer, intent, resolvedType, userId, targetUserId, flags, pkgName, crossProfileIntentFiltersByUser.valueAt(index), hasNonNegativePriorityResultFromParent.get(currentUserId), pkgSettingFunction); hasNonNegativePriorityResult, pkgSettingFunction); crossProfileDomainInfos.addAll(crossProfileInfos); hasNonNegativePriorityResultFromParent.put(targetUserId, hasNonNegativePriority(crossProfileInfos)); visitedUserIds.add(targetUserId); /* Adding target user to queue if flag Loading @@ -221,10 +219,12 @@ public class CrossProfileIntentResolverEngine { } } if (allowChainedResolution) { pendingUsers.add(targetUserId); } visitedUserIds.add(targetUserId); crossProfileDomainInfos.addAll(resolveIntentInternal(computer, intent, resolvedType, sourceUserId, targetUserId, flags, pkgName, hasNonNegativePriority(crossProfileInfos), pkgSettingFunction, visitedUserIds)); } } } Loading Loading @@ -275,36 +275,32 @@ public class CrossProfileIntentResolverEngine { public boolean canReachTo(@NonNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { return canReachToInternal(computer, intent, resolvedType, sourceUserId, targetUserId); Set<Integer> visitedUserIds = new HashSet<>(); return canReachToInternal(computer, intent, resolvedType, sourceUserId, targetUserId, visitedUserIds); } /** * Returns true if we source user can reach target user for given intent. The source can * directly or indirectly reach to target. This will perform breadth first search to check if * directly or indirectly reach to target. This will perform depth first search to check if * source can reach target. * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi} * @param intent request * @param resolvedType the MIME data type of intent request * @param sourceUserId source user * @param targetUserId target user * @param visitedUserIds users for which resolution is checked * @return true if we source user can reach target user for given intent */ private boolean canReachToInternal(@NonNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { @UserIdInt int targetUserId, Set<Integer> visitedUserIds) { if (sourceUserId == targetUserId) return true; Queue<Integer> pendingUsers = new ArrayDeque<>(); Set<Integer> visitedUserIds = new HashSet<>(); visitedUserIds.add(sourceUserId); pendingUsers.add(sourceUserId); while (!pendingUsers.isEmpty()) { int currentUserId = pendingUsers.poll(); List<CrossProfileIntentFilter> matches = computer.getMatchingCrossProfileIntentFilters(intent, resolvedType, currentUserId); computer.getMatchingCrossProfileIntentFilters(intent, resolvedType, sourceUserId); if (matches != null) { for (int index = 0; index < matches.size(); index++) { CrossProfileIntentFilter crossProfileIntentFilter = matches.get(index); Loading @@ -323,8 +319,10 @@ public class CrossProfileIntentResolverEngine { */ if ((CrossProfileIntentFilter.FLAG_ALLOW_CHAINED_RESOLUTION & crossProfileIntentFilter.mFlags) != 0) { pendingUsers.add(crossProfileIntentFilter.mTargetUserId); visitedUserIds.add(crossProfileIntentFilter.mTargetUserId); if (canReachToInternal(computer, intent, resolvedType, crossProfileIntentFilter.mTargetUserId, targetUserId, visitedUserIds)) { return true; } } } Loading Loading @@ -628,8 +626,7 @@ public class CrossProfileIntentResolverEngine { categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) { List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); UserInfo sourceUserInfo = umInternal.getUserInfo(sourceUserId); UserInfo sourceUserInfo = mUserManagerInternal.getUserInfo(sourceUserId); for (int index = 0; index < categorizeResolveInfoByTargetUser.size(); index++) { Loading @@ -639,7 +636,7 @@ public class CrossProfileIntentResolverEngine { } else { // finding cross profile strategy based on source and target user CrossProfileResolver crossProfileIntentResolver = chooseCrossProfileResolver(computer, sourceUserInfo, umInternal chooseCrossProfileResolver(computer, sourceUserInfo, mUserManagerInternal .getUserInfo(categorizeResolveInfoByTargetUser.keyAt(index))); // if strategy is available call it and add its filtered results if (crossProfileIntentResolver != null) { Loading Loading
services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java +132 −135 Original line number Diff line number Diff line Loading @@ -36,18 +36,15 @@ import android.util.FeatureFlagUtils; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.server.LocalServices; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationUtils; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.function.Function; Loading @@ -62,6 +59,7 @@ public class CrossProfileIntentResolverEngine { private final DomainVerificationManagerInternal mDomainVerificationManager; private final DefaultAppProvider mDefaultAppProvider; private final Context mContext; private final UserManagerInternal mUserManagerInternal; public CrossProfileIntentResolverEngine(UserManagerService userManager, DomainVerificationManagerInternal domainVerificationManager, Loading @@ -70,6 +68,7 @@ public class CrossProfileIntentResolverEngine { mDomainVerificationManager = domainVerificationManager; mDefaultAppProvider = defaultAppProvider; mContext = context; mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); } /** Loading @@ -92,14 +91,14 @@ public class CrossProfileIntentResolverEngine { String resolvedType, int userId, long flags, String pkgName, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction) { return resolveIntentInternal(computer, intent, resolvedType, userId, flags, pkgName, hasNonNegativePriorityResult, pkgSettingFunction); return resolveIntentInternal(computer, intent, resolvedType, userId, userId, flags, pkgName, hasNonNegativePriorityResult, pkgSettingFunction, null); } /** * Resolves intent in directly linked profiles and return list of {@link CrossProfileDomainInfo} * which contains {@link ResolveInfo}. This would also iteratively call profiles not directly * linked using Breadth First Search. * which contains {@link ResolveInfo}. This would also recursively call profiles not directly * linked using Depth First Search. * * It first finds {@link CrossProfileIntentFilter} configured in current profile to find list of * target user profiles that can serve current intent request. It uses corresponding strategy Loading @@ -108,51 +107,48 @@ public class CrossProfileIntentResolverEngine { * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi} * @param intent request * @param resolvedType the MIME data type of intent request * @param userId source user for which intent request is called * @param sourceUserId source user for which intent request is called * @param userId current user for cross profile resolution * @param flags used for intent resolution * @param pkgName the application package name this Intent is limited to. * @param hasNonNegativePriorityResult signifies if current profile have any non-negative(active * and valid) ResolveInfo in current profile. * @param pkgSettingFunction function to find PackageStateInternal for given package * @param visitedUserIds users for which we have already performed resolution * @return list of {@link CrossProfileDomainInfo} from linked profiles. */ private List<CrossProfileDomainInfo> resolveIntentInternal(@NonNull Computer computer, Intent intent, String resolvedType, int userId, long flags, String pkgName, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction) { Queue<Integer> pendingUsers = new ArrayDeque<>(); Set<Integer> visitedUserIds = new HashSet<>(); SparseBooleanArray hasNonNegativePriorityResultFromParent = new SparseBooleanArray(); visitedUserIds.add(userId); pendingUsers.add(userId); hasNonNegativePriorityResultFromParent.put(userId, hasNonNegativePriorityResult); UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); Intent intent, String resolvedType, int sourceUserId, int userId, long flags, String pkgName, boolean hasNonNegativePriorityResult, Function<String, PackageStateInternal> pkgSettingFunction, Set<Integer> visitedUserIds) { if (visitedUserIds != null) visitedUserIds.add(userId); List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); while (!pendingUsers.isEmpty()) { int currentUserId = pendingUsers.poll(); List<CrossProfileIntentFilter> matchingFilters = computer.getMatchingCrossProfileIntentFilters(intent, resolvedType, currentUserId); userId); if (matchingFilters == null || matchingFilters.isEmpty()) { /** if intent is web intent, checking if parent profile should handle the intent * even if there is no matching filter. The configuration is based on user profile * restriction android.os.UserManager#ALLOW_PARENT_PROFILE_APP_LINKING **/ if (currentUserId == userId && intent.hasWebURI()) { UserInfo parent = computer.getProfileParent(currentUserId); if (sourceUserId == userId && intent.hasWebURI()) { UserInfo parent = computer.getProfileParent(userId); if (parent != null) { CrossProfileDomainInfo generalizedCrossProfileDomainInfo = computer .getCrossProfileDomainPreferredLpr(intent, resolvedType, flags, currentUserId, parent.id); userId, parent.id); if (generalizedCrossProfileDomainInfo != null) { crossProfileDomainInfos.add(generalizedCrossProfileDomainInfo); } } } continue; return crossProfileDomainInfos; } UserInfo sourceUserInfo = umInternal.getUserInfo(currentUserId); UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); // Grouping the CrossProfileIntentFilters based on targerId SparseArray<List<CrossProfileIntentFilter>> crossProfileIntentFiltersByUser = Loading @@ -170,6 +166,11 @@ public class CrossProfileIntentResolverEngine { .add(crossProfileIntentFilter); } if (visitedUserIds == null) { visitedUserIds = new HashSet<>(); visitedUserIds.add(userId); } /* For each target user, we would call their corresponding strategy {@link CrossProfileResolver} to resolve intent in corresponding user Loading @@ -183,11 +184,11 @@ public class CrossProfileIntentResolverEngine { continue; } UserInfo targetUserInfo = umInternal.getUserInfo(targetUserId); UserInfo targetUserInfo = mUserManagerInternal.getUserInfo(targetUserId); // Choosing strategy based on source and target user CrossProfileResolver crossProfileResolver = chooseCrossProfileResolver(computer, sourceUserInfo, targetUserInfo); chooseCrossProfileResolver(computer, userInfo, targetUserInfo); /* If {@link CrossProfileResolver} is available for source,target pair we will call it to Loading @@ -195,15 +196,12 @@ public class CrossProfileIntentResolverEngine { */ if (crossProfileResolver != null) { List<CrossProfileDomainInfo> crossProfileInfos = crossProfileResolver .resolveIntent(computer, intent, resolvedType, currentUserId, .resolveIntent(computer, intent, resolvedType, userId, targetUserId, flags, pkgName, crossProfileIntentFiltersByUser.valueAt(index), hasNonNegativePriorityResultFromParent.get(currentUserId), pkgSettingFunction); hasNonNegativePriorityResult, pkgSettingFunction); crossProfileDomainInfos.addAll(crossProfileInfos); hasNonNegativePriorityResultFromParent.put(targetUserId, hasNonNegativePriority(crossProfileInfos)); visitedUserIds.add(targetUserId); /* Adding target user to queue if flag Loading @@ -221,10 +219,12 @@ public class CrossProfileIntentResolverEngine { } } if (allowChainedResolution) { pendingUsers.add(targetUserId); } visitedUserIds.add(targetUserId); crossProfileDomainInfos.addAll(resolveIntentInternal(computer, intent, resolvedType, sourceUserId, targetUserId, flags, pkgName, hasNonNegativePriority(crossProfileInfos), pkgSettingFunction, visitedUserIds)); } } } Loading Loading @@ -275,36 +275,32 @@ public class CrossProfileIntentResolverEngine { public boolean canReachTo(@NonNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { return canReachToInternal(computer, intent, resolvedType, sourceUserId, targetUserId); Set<Integer> visitedUserIds = new HashSet<>(); return canReachToInternal(computer, intent, resolvedType, sourceUserId, targetUserId, visitedUserIds); } /** * Returns true if we source user can reach target user for given intent. The source can * directly or indirectly reach to target. This will perform breadth first search to check if * directly or indirectly reach to target. This will perform depth first search to check if * source can reach target. * @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi} * @param intent request * @param resolvedType the MIME data type of intent request * @param sourceUserId source user * @param targetUserId target user * @param visitedUserIds users for which resolution is checked * @return true if we source user can reach target user for given intent */ private boolean canReachToInternal(@NonNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, @UserIdInt int sourceUserId, @UserIdInt int targetUserId) { @UserIdInt int targetUserId, Set<Integer> visitedUserIds) { if (sourceUserId == targetUserId) return true; Queue<Integer> pendingUsers = new ArrayDeque<>(); Set<Integer> visitedUserIds = new HashSet<>(); visitedUserIds.add(sourceUserId); pendingUsers.add(sourceUserId); while (!pendingUsers.isEmpty()) { int currentUserId = pendingUsers.poll(); List<CrossProfileIntentFilter> matches = computer.getMatchingCrossProfileIntentFilters(intent, resolvedType, currentUserId); computer.getMatchingCrossProfileIntentFilters(intent, resolvedType, sourceUserId); if (matches != null) { for (int index = 0; index < matches.size(); index++) { CrossProfileIntentFilter crossProfileIntentFilter = matches.get(index); Loading @@ -323,8 +319,10 @@ public class CrossProfileIntentResolverEngine { */ if ((CrossProfileIntentFilter.FLAG_ALLOW_CHAINED_RESOLUTION & crossProfileIntentFilter.mFlags) != 0) { pendingUsers.add(crossProfileIntentFilter.mTargetUserId); visitedUserIds.add(crossProfileIntentFilter.mTargetUserId); if (canReachToInternal(computer, intent, resolvedType, crossProfileIntentFilter.mTargetUserId, targetUserId, visitedUserIds)) { return true; } } } Loading Loading @@ -628,8 +626,7 @@ public class CrossProfileIntentResolverEngine { categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) { List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>(); UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); UserInfo sourceUserInfo = umInternal.getUserInfo(sourceUserId); UserInfo sourceUserInfo = mUserManagerInternal.getUserInfo(sourceUserId); for (int index = 0; index < categorizeResolveInfoByTargetUser.size(); index++) { Loading @@ -639,7 +636,7 @@ public class CrossProfileIntentResolverEngine { } else { // finding cross profile strategy based on source and target user CrossProfileResolver crossProfileIntentResolver = chooseCrossProfileResolver(computer, sourceUserInfo, umInternal chooseCrossProfileResolver(computer, sourceUserInfo, mUserManagerInternal .getUserInfo(categorizeResolveInfoByTargetUser.keyAt(index))); // if strategy is available call it and add its filtered results if (crossProfileIntentResolver != null) { Loading