diff options
| author | 2015-12-01 20:19:03 +0000 | |
|---|---|---|
| committer | 2015-12-01 20:19:03 +0000 | |
| commit | 807e01cb47c2d5442f76e27b70a7206f77ed76d8 (patch) | |
| tree | ade04cafa0dc42f12930fc2352c95f8eae55b8cd | |
| parent | 08998124567e8f4063c20daf836ce1fb57c459e3 (diff) | |
Introduce ONLY_IF_NO_MATCH_FOUND in CrossProfileIntentFilter
With this flag, activities in other profiles can respond to the intent
only if no intent-filter with non-negative priority in current profile can
respond to it.
It is designed like this because activities with negative priority
intentfilter are always used as a fallback in case no one can respond
to the intent. In this case, we expect there is a "real" activity in
other profiles can handle the intentfilter
Here is the example activity that handle the call related intents when
there is no dialer.
NonPhoneActivity.java in Contacts app is an example.
https://github.com/android/platform_packages_apps_contacts/blob/master/AndroidManifest.xml#L461
Bug: 25760508
Change-Id: Ife2a7c19e91ddf5d2e81ad09bd4cf712cdcdb986
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 34 |
2 files changed, 36 insertions, 9 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 0c28008b1b87..0e8336e4b348 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -259,6 +259,14 @@ public abstract class PackageManager { */ public static final int SKIP_CURRENT_PROFILE = 0x00000002; + /** + * Flag for {@link addCrossProfileIntentFilter}: if this flag is set: + * activities in the other profiles can respond to the intent only if no activity with + * non-negative priority in current profile can respond to the intent. + * @hide + */ + public static final int ONLY_IF_NO_MATCH_FOUND = 0x00000004; + /** @hide */ @IntDef({PERMISSION_GRANTED, PERMISSION_DENIED}) @Retention(RetentionPolicy.SOURCE) @@ -4629,7 +4637,8 @@ public abstract class PackageManager { * @param filter The {@link IntentFilter} the intent has to match * @param sourceUserId The source user id. * @param targetUserId The target user id. - * @param flags The only possible value is {@link SKIP_CURRENT_PROFILE} + * @param flags The possible values are {@link SKIP_CURRENT_PROFILE} and + * {@link ONLY_IF_NO_MATCH_FOUND}. * @hide */ public abstract void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4bc79cb13fce..4f0cf8fb76b7 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4833,15 +4833,21 @@ public class PackageManagerService extends IPackageManager.Stub { // Check for results in the current profile. List<ResolveInfo> result = mActivities.queryIntent( intent, resolvedType, flags, userId); + result = filterIfNotSystemUser(result, userId); // Check for cross profile results. + boolean hasNonNegativePriorityResult = hasNonNegativePriority(result); xpResolveInfo = queryCrossProfileIntents( - matchingFilters, intent, resolvedType, flags, userId); + matchingFilters, intent, resolvedType, flags, userId, + hasNonNegativePriorityResult); if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) { - result.add(xpResolveInfo); - Collections.sort(result, mResolvePrioritySorter); + boolean isVisibleToUser = filterIfNotSystemUser( + Collections.singletonList(xpResolveInfo), userId).size() > 0; + if (isVisibleToUser) { + result.add(xpResolveInfo); + Collections.sort(result, mResolvePrioritySorter); + } } - result = filterIfNotSystemUser(result, userId); if (hasWebURI(intent)) { CrossProfileDomainInfo xpDomainInfo = null; final UserInfo parent = getProfileParent(userId); @@ -4974,6 +4980,14 @@ public class PackageManagerService extends IPackageManager.Stub { return resolveInfos; } + /** + * @param resolveInfos list of resolve infos in descending priority order + * @return if the list contains a resolve info with non-negative priority + */ + private boolean hasNonNegativePriority(List<ResolveInfo> resolveInfos) { + return resolveInfos.size() > 0 && resolveInfos.get(0).priority >= 0; + } + private static boolean hasWebURI(Intent intent) { if (intent.getData() == null) { return false; @@ -5177,10 +5191,10 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } - // Return matching ResolveInfo if any for skip current profile intent filters. + // Return matching ResolveInfo in target user if any. private ResolveInfo queryCrossProfileIntents( List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType, - int flags, int sourceUserId) { + int flags, int sourceUserId, boolean matchInCurrentProfile) { if (matchingFilters != null) { // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and // match the same intent. For performance reasons, it is better not to @@ -5190,8 +5204,12 @@ public class PackageManagerService extends IPackageManager.Stub { for (int i = 0; i < size; i++) { CrossProfileIntentFilter filter = matchingFilters.get(i); int targetUserId = filter.getTargetUserId(); - if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) == 0 - && !alreadyTriedUserIds.get(targetUserId)) { + boolean skipCurrentProfile = + (filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0; + boolean skipCurrentProfileIfNoMatchFound = + (filter.getFlags() & PackageManager.ONLY_IF_NO_MATCH_FOUND) != 0; + if (!skipCurrentProfile && !alreadyTriedUserIds.get(targetUserId) + && (!skipCurrentProfileIfNoMatchFound || !matchInCurrentProfile)) { // Checking if there are activities in the target user that can handle the // intent. ResolveInfo resolveInfo = createForwardingResolveInfo(filter, intent, |