summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tony Mak <tonymak@google.com> 2015-12-01 20:19:03 +0000
committer Tony Mak <tonymak@google.com> 2015-12-01 20:19:03 +0000
commit807e01cb47c2d5442f76e27b70a7206f77ed76d8 (patch)
treeade04cafa0dc42f12930fc2352c95f8eae55b8cd
parent08998124567e8f4063c20daf836ce1fb57c459e3 (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.java11
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java34
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,