Merge "Introducing crossProfileIntentFilters that skip the current profile."
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index de0396e..5e17e1a 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1457,10 +1457,10 @@
* @hide
*/
@Override
- public void addCrossProfileIntentFilter(IntentFilter filter, boolean removable,
- int sourceUserId, int targetUserId) {
+ public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
+ int flags) {
try {
- mPM.addCrossProfileIntentFilter(filter, removable, sourceUserId, targetUserId);
+ mPM.addCrossProfileIntentFilter(filter, sourceUserId, targetUserId, flags);
} catch (RemoteException e) {
// Should never happen!
}
@@ -1470,15 +1470,6 @@
* @hide
*/
@Override
- public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int sourceUserId,
- int targetUserId) {
- addCrossProfileIntentFilter(filter, removable, sourceUserId, targetUserId);
- }
-
- /**
- * @hide
- */
- @Override
public void clearCrossProfileIntentFilters(int sourceUserId) {
try {
mPM.clearCrossProfileIntentFilters(sourceUserId);
@@ -1487,14 +1478,6 @@
}
}
- /**
- * @hide
- */
- @Override
- public void clearForwardingIntentFilters(int sourceUserId) {
- clearCrossProfileIntentFilters(sourceUserId);
- }
-
private final ContextImpl mContext;
private final IPackageManager mPM;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 70668e1..00e7918 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -248,8 +248,8 @@
void clearPackagePersistentPreferredActivities(String packageName, int userId);
- void addCrossProfileIntentFilter(in IntentFilter filter, boolean removable, int sourceUserId,
- int targetUserId);
+ void addCrossProfileIntentFilter(in IntentFilter intentFilter, int sourceUserId, int targetUserId,
+ int flags);
void clearCrossProfileIntentFilters(int sourceUserId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5d55b0a1..b5ceebe 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -196,6 +196,22 @@
*/
public static final int MATCH_DEFAULT_ONLY = 0x00010000;
+ /**
+ * Flag for {@link addCrossProfileIntentFilter}: if the cross-profile intent has been set by the
+ * profile owner.
+ * @hide
+ */
+ public static final int SET_BY_PROFILE_OWNER= 0x00000001;
+
+ /**
+ * Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
+ * when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current
+ * profile will be skipped.
+ * Only activities in the target user can respond to the intent.
+ * @hide
+ */
+ public static final int SKIP_CURRENT_PROFILE = 0x00000002;
+
/** @hide */
@IntDef({PERMISSION_GRANTED, PERMISSION_DENIED})
@Retention(RetentionPolicy.SOURCE)
@@ -3583,30 +3599,14 @@
* {@link CrossProfileIntentFilter}
* @hide
*/
- public abstract void addCrossProfileIntentFilter(IntentFilter filter, boolean removable,
- int sourceUserId, int targetUserId);
+ public abstract void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId,
+ int targetUserId, int flags);
/**
- * @hide
- * @deprecated
- * TODO: remove it as soon as the code of ManagedProvisionning is updated
- */
- public abstract void addForwardingIntentFilter(IntentFilter filter, boolean removable,
- int sourceUserId, int targetUserId);
-
- /**
- * Clearing removable {@link CrossProfileIntentFilter}s which have the specified user as their
- * source
+ * Clearing {@link CrossProfileIntentFilter}s which have the specified user as their
+ * source, and have been set by the profile owner
* @param sourceUserId
- * be cleared.
* @hide
*/
public abstract void clearCrossProfileIntentFilters(int sourceUserId);
-
- /**
- * @hide
- * @deprecated
- * TODO: remove it as soon as the code of ManagedProvisionning is updated
- */
- public abstract void clearForwardingIntentFilters(int sourceUserId);
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
index 3d432dc..3ce19c1f 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
@@ -32,36 +32,32 @@
*/
class CrossProfileIntentFilter extends IntentFilter {
private static final String ATTR_TARGET_USER_ID = "targetUserId";
- private static final String ATTR_USER_ID_DEST = "userIdDest";//Old name. Kept for compatibility.
- private static final String ATTR_REMOVABLE = "removable";
+ private static final String ATTR_FLAGS = "flags";
private static final String ATTR_FILTER = "filter";
private static final String TAG = "CrossProfileIntentFilter";
// If the intent matches the IntentFilter, then it can be forwarded to this userId.
final int mTargetUserId;
- boolean mRemovable;
+ final int mFlags;
- CrossProfileIntentFilter(IntentFilter filter, boolean removable, int targetUserId) {
+ CrossProfileIntentFilter(IntentFilter filter, int targetUserId, int flags) {
super(filter);
mTargetUserId = targetUserId;
- mRemovable = removable;
+ mFlags = flags;
}
public int getTargetUserId() {
return mTargetUserId;
}
- public boolean isRemovable() {
- return mRemovable;
+ public int getFlags() {
+ return mFlags;
}
CrossProfileIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException {
String targetUserIdString = parser.getAttributeValue(null, ATTR_TARGET_USER_ID);
if (targetUserIdString == null) {
- targetUserIdString = parser.getAttributeValue(null, ATTR_USER_ID_DEST);
- }
- if (targetUserIdString == null) {
String msg = "Missing element under " + TAG +": " + ATTR_TARGET_USER_ID + " at " +
parser.getPositionDescription();
PackageManagerService.reportSettingsProblem(Log.WARN, msg);
@@ -69,9 +65,14 @@
} else {
mTargetUserId = Integer.parseInt(targetUserIdString);
}
- String removableString = parser.getAttributeValue(null, ATTR_REMOVABLE);
- if (removableString != null) {
- mRemovable = Boolean.parseBoolean(removableString);
+ String flagsString = parser.getAttributeValue(null, ATTR_FLAGS);
+ if (flagsString == null) {
+ String msg = "Missing element under " + TAG +": " + ATTR_FLAGS + " at " +
+ parser.getPositionDescription();
+ PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+ mFlags = 0;
+ } else {
+ mFlags = Integer.parseInt(flagsString);
}
int outerDepth = parser.getDepth();
String tagName = parser.getName();
@@ -104,7 +105,7 @@
public void writeToXml(XmlSerializer serializer) throws IOException {
serializer.attribute(null, ATTR_TARGET_USER_ID, Integer.toString(mTargetUserId));
- serializer.attribute(null, ATTR_REMOVABLE, Boolean.toString(mRemovable));
+ serializer.attribute(null, ATTR_FLAGS, Integer.toString(mFlags));
serializer.startTag(null, ATTR_FILTER);
super.writeToXml(serializer);
serializer.endTag(null, ATTR_FILTER);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2f40f2a..a7fc7eb 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -147,6 +147,7 @@
import android.util.PrintStreamPrinter;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.Display;
@@ -3347,7 +3348,7 @@
}
/*
- * Returns if intent can be forwarded from the userId from to dest
+ * Returns if intent can be forwarded from the sourceUserId to the targetUserId
*/
@Override
public boolean canForwardTo(Intent intent, String resolvedType, int sourceUserId,
@@ -3367,9 +3368,9 @@
private List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent,
String resolvedType, int userId) {
- CrossProfileIntentResolver cpir = mSettings.mCrossProfileIntentResolvers.get(userId);
- if (cpir != null) {
- return cpir.queryIntent(intent, resolvedType, false, userId);
+ CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId);
+ if (resolver != null) {
+ return resolver.queryIntent(intent, resolvedType, false, userId);
}
return null;
}
@@ -3402,36 +3403,24 @@
synchronized (mPackages) {
final String pkgName = intent.getPackage();
if (pkgName == null) {
- List<ResolveInfo> result =
- mActivities.queryIntent(intent, resolvedType, flags, userId);
- // Checking if we can forward the intent to another user
- List<CrossProfileIntentFilter> cpifs =
+ List<ResolveInfo> result;
+ List<CrossProfileIntentFilter> matchingFilters =
getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
- if (cpifs != null) {
- CrossProfileIntentFilter crossProfileIntentFilterWithResult = null;
- HashSet<Integer> alreadyTriedUserIds = new HashSet<Integer>();
- for (CrossProfileIntentFilter cpif : cpifs) {
- int targetUserId = cpif.getTargetUserId();
- // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and
- // match the same an intent. For performance reasons, it is better not to
- // run queryIntent twice for the same userId
- if (!alreadyTriedUserIds.contains(targetUserId)) {
- List<ResolveInfo> resultUser = mActivities.queryIntent(intent,
- resolvedType, flags, targetUserId);
- if (resultUser != null) {
- crossProfileIntentFilterWithResult = cpif;
- // As soon as there is a match in another user, we add the
- // intentForwarderActivity to the list of ResolveInfo.
- break;
- }
- alreadyTriedUserIds.add(targetUserId);
- }
- }
- if (crossProfileIntentFilterWithResult != null) {
- ResolveInfo forwardingResolveInfo = createForwardingResolveInfo(
- crossProfileIntentFilterWithResult, userId);
- result.add(forwardingResolveInfo);
- }
+ // Check for results that need to skip the current profile.
+ ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
+ resolvedType, flags, userId);
+ if (resolveInfo != null) {
+ result = new ArrayList<ResolveInfo>(1);
+ result.add(resolveInfo);
+ return result;
+ }
+ // Check for results in the current profile.
+ result = mActivities.queryIntent(intent, resolvedType, flags, userId);
+ // Check for cross profile results.
+ resolveInfo = queryCrossProfileIntents(
+ matchingFilters, intent, resolvedType, flags, userId);
+ if (resolveInfo != null) {
+ result.add(resolveInfo);
}
return result;
}
@@ -3444,10 +3433,68 @@
}
}
- private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter cpif,
+ private ResolveInfo querySkipCurrentProfileIntents(
+ List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
+ int flags, int sourceUserId) {
+ if (matchingFilters != null) {
+ int size = matchingFilters.size();
+ for (int i = 0; i < size; i ++) {
+ CrossProfileIntentFilter filter = matchingFilters.get(i);
+ if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0) {
+ // Checking if there are activities in the target user that can handle the
+ // intent.
+ ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType,
+ flags, sourceUserId);
+ if (resolveInfo != null) {
+ return createForwardingResolveInfo(filter, sourceUserId);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ // Return matching ResolveInfo if any for skip current profile intent filters.
+ private ResolveInfo queryCrossProfileIntents(
+ List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
+ int flags, int sourceUserId) {
+ 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
+ // run queryIntent twice for the same userId
+ SparseBooleanArray alreadyTriedUserIds = new SparseBooleanArray();
+ int size = matchingFilters.size();
+ 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)) {
+ // Checking if there are activities in the target user that can handle the
+ // intent.
+ ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType,
+ flags, sourceUserId);
+ if (resolveInfo != null) return resolveInfo;
+ alreadyTriedUserIds.put(targetUserId, true);
+ }
+ }
+ }
+ return null;
+ }
+
+ private ResolveInfo checkTargetCanHandle(CrossProfileIntentFilter filter, Intent intent,
+ String resolvedType, int flags, int sourceUserId) {
+ List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
+ resolvedType, flags, filter.getTargetUserId());
+ if (resultTargetUser != null) {
+ return createForwardingResolveInfo(filter, sourceUserId);
+ }
+ return null;
+ }
+
+ private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter,
int sourceUserId) {
String className;
- int targetUserId = cpif.getTargetUserId();
+ int targetUserId = filter.getTargetUserId();
if (targetUserId == UserHandle.USER_OWNER) {
className = FORWARD_INTENT_TO_USER_OWNER;
} else {
@@ -3463,7 +3510,7 @@
forwardingResolveInfo.preferredOrder = 0;
forwardingResolveInfo.match = 0;
forwardingResolveInfo.isDefault = true;
- forwardingResolveInfo.filter = cpif;
+ forwardingResolveInfo.filter = filter;
return forwardingResolveInfo;
}
@@ -11539,17 +11586,18 @@
}
@Override
- public void addCrossProfileIntentFilter(IntentFilter filter, boolean removable,
- int sourceUserId, int targetUserId) {
+ public void addCrossProfileIntentFilter(IntentFilter intentFilter, int sourceUserId,
+ int targetUserId, int flags) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
- if (filter.countActions() == 0) {
+ if (intentFilter.countActions() == 0) {
Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions");
return;
}
synchronized (mPackages) {
- mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(
- new CrossProfileIntentFilter(filter, removable, targetUserId));
+ CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter,
+ targetUserId, flags);
+ mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter);
mSettings.writePackageRestrictionsLPr(sourceUserId);
}
}
@@ -11559,12 +11607,14 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
synchronized (mPackages) {
- CrossProfileIntentResolver cpir =
+ CrossProfileIntentResolver resolver =
mSettings.editCrossProfileIntentResolverLPw(sourceUserId);
HashSet<CrossProfileIntentFilter> set =
- new HashSet<CrossProfileIntentFilter>(cpir.filterSet());
- for (CrossProfileIntentFilter cpif : set) {
- if (cpif.isRemovable()) cpir.removeFilter(cpif);
+ new HashSet<CrossProfileIntentFilter>(resolver.filterSet());
+ for (CrossProfileIntentFilter filter : set) {
+ if ((filter.getFlags() & PackageManager.SET_BY_PROFILE_OWNER) != 0) {
+ resolver.removeFilter(filter);
+ }
}
mSettings.writePackageRestrictionsLPr(sourceUserId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5cf5713..4897b1d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3454,12 +3454,12 @@
long id = Binder.clearCallingIdentity();
try {
if ((flags & DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED) != 0) {
- pm.addCrossProfileIntentFilter(filter, true /*removable*/, callingUserId,
- UserHandle.USER_OWNER);
+ pm.addCrossProfileIntentFilter(filter, callingUserId, UserHandle.USER_OWNER,
+ PackageManager.SET_BY_PROFILE_OWNER);
}
if ((flags & DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT) != 0) {
- pm.addCrossProfileIntentFilter(filter, true /*removable*/, UserHandle.USER_OWNER,
- callingUserId);
+ pm.addCrossProfileIntentFilter(filter, UserHandle.USER_OWNER, callingUserId,
+ PackageManager.SET_BY_PROFILE_OWNER);
}
} catch (RemoteException re) {
// Shouldn't happen
@@ -3480,6 +3480,8 @@
long id = Binder.clearCallingIdentity();
try {
pm.clearCrossProfileIntentFilters(callingUserId);
+ // If we want to support multiple managed profiles, we will have to only remove
+ // those that have callingUserId as their target.
pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER);
} catch (RemoteException re) {
// Shouldn't happen
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 17db1b4..a3b32b3 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -707,17 +707,8 @@
* @hide
*/
@Override
- public void addCrossProfileIntentFilter(IntentFilter filter, boolean removable,
- int sourceUserId, int targetUserId) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
- @Override
- public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int sourceUserId,
- int targetUserId) {
+ public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
+ int flags) {
throw new UnsupportedOperationException();
}
@@ -729,14 +720,6 @@
throw new UnsupportedOperationException();
}
- /**
- * @hide
- */
- @Override
- public void clearForwardingIntentFilters(int sourceUserId) {
- throw new UnsupportedOperationException();
- }
-
/** {@hide} */
public PackageInstaller getPackageInstaller() {
throw new UnsupportedOperationException();