summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java311
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java9
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java9
-rw-r--r--services/core/java/com/android/server/am/UriPermission.java50
-rw-r--r--services/core/java/com/android/server/am/UriPermissionOwner.java89
5 files changed, 266 insertions, 202 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ecbb0d9..1bbdf3b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,8 +17,10 @@
package com.android.server.am;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
@@ -724,6 +726,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final String ATTR_URI = "uri";
private static final String ATTR_MODE_FLAGS = "modeFlags";
private static final String ATTR_CREATED_TIME = "createdTime";
+ private static final String ATTR_PREFIX = "prefix";
/**
* Global set of specific {@link Uri} permissions that have been granted.
@@ -731,8 +734,41 @@ public final class ActivityManagerService extends ActivityManagerNative
* to {@link UriPermission#uri} to {@link UriPermission}.
*/
@GuardedBy("this")
- private final SparseArray<ArrayMap<Uri, UriPermission>>
- mGrantedUriPermissions = new SparseArray<ArrayMap<Uri, UriPermission>>();
+ private final SparseArray<ArrayMap<GrantUri, UriPermission>>
+ mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>();
+
+ public static class GrantUri {
+ public final Uri uri;
+ public final boolean prefix;
+
+ public GrantUri(Uri uri, boolean prefix) {
+ this.uri = uri;
+ this.prefix = prefix;
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof GrantUri) {
+ GrantUri other = (GrantUri) o;
+ return uri.equals(other.uri) && prefix == other.prefix;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ if (prefix) {
+ return uri.toString() + " [prefix]";
+ } else {
+ return uri.toString();
+ }
+ }
+ }
CoreSettingsObserver mCoreSettingsObserver;
@@ -5822,7 +5858,7 @@ public final class ActivityManagerService extends ActivityManagerNative
* in {@link ContentProvider}.
*/
private final boolean checkHoldingPermissionsLocked(
- IPackageManager pm, ProviderInfo pi, Uri uri, int uid, int modeFlags) {
+ IPackageManager pm, ProviderInfo pi, Uri uri, int uid, final int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
@@ -5918,18 +5954,17 @@ public final class ActivityManagerService extends ActivityManagerNative
return pi;
}
- private UriPermission findUriPermissionLocked(int targetUid, Uri uri) {
- ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+ private UriPermission findUriPermissionLocked(int targetUid, GrantUri uri) {
+ final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris != null) {
return targetUris.get(uri);
- } else {
- return null;
}
+ return null;
}
- private UriPermission findOrCreateUriPermissionLocked(
- String sourcePkg, String targetPkg, int targetUid, Uri uri) {
- ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+ private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
+ String targetPkg, int targetUid, GrantUri uri) {
+ ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris == null) {
targetUris = Maps.newArrayMap();
mGrantedUriPermissions.put(targetUid, targetUris);
@@ -5945,20 +5980,36 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private final boolean checkUriPermissionLocked(
- Uri uri, int uid, int modeFlags, int minStrength) {
+ Uri uri, int uid, final int modeFlags, int minStrength) {
// Root gets to do everything.
if (uid == 0) {
return true;
}
- ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
if (perms == null) return false;
- UriPermission perm = perms.get(uri);
- if (perm == null) return false;
- return perm.getStrength(modeFlags) >= minStrength;
+
+ // First look for exact match
+ final UriPermission exactPerm = perms.get(new GrantUri(uri, false));
+ if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
+ return true;
+ }
+
+ // No exact match, look for prefixes
+ final int N = perms.size();
+ for (int i = 0; i < N; i++) {
+ final UriPermission perm = perms.valueAt(i);
+ if (perm.uri.prefix && uri.isPathPrefixMatch(perm.uri.uri)
+ && perm.getStrength(modeFlags) >= minStrength) {
+ return true;
+ }
+ }
+
+ return false;
}
@Override
- public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
+ public int checkUriPermission(Uri uri, int pid, int uid, final int modeFlags) {
enforceNotIsolatedCaller("checkUriPermission");
// Another redirected-binder-call permissions check as in
@@ -5990,11 +6041,8 @@ public final class ActivityManagerService extends ActivityManagerNative
* lastTargetUid else set that to -1.
*/
int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
- Uri uri, int modeFlags, int lastTargetUid) {
- final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
- modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- if (modeFlags == 0) {
+ Uri uri, final int modeFlags, int lastTargetUid) {
+ if (!Intent.isAccessUriMode(modeFlags)) {
return -1;
}
@@ -6089,6 +6137,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (callingUid != Process.myUid()) {
if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
// Require they hold a strong enough Uri permission
+ final boolean persistable =
+ (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
: UriPermission.STRENGTH_OWNED;
if (!checkUriPermissionLocked(uri, callingUid, modeFlags, minStrength)) {
@@ -6103,19 +6153,16 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("checkGrantUriPermission");
synchronized(this) {
return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
}
}
- void grantUriPermissionUncheckedLocked(
- int targetUid, String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
- final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
- modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- if (modeFlags == 0) {
+ void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, Uri uri,
+ final int modeFlags, UriPermissionOwner owner) {
+ if (!Intent.isAccessUriMode(modeFlags)) {
return;
}
@@ -6133,13 +6180,14 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
+ final boolean prefix = (modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0;
final UriPermission perm = findOrCreateUriPermissionLocked(
- pi.packageName, targetPkg, targetUid, uri);
- perm.grantModes(modeFlags, persistable, owner);
+ pi.packageName, targetPkg, targetUid, new GrantUri(uri, prefix));
+ perm.grantModes(modeFlags, owner);
}
void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri,
- int modeFlags, UriPermissionOwner owner) {
+ final int modeFlags, UriPermissionOwner owner) {
if (targetPkg == null) {
throw new NullPointerException("targetPkg");
}
@@ -6253,7 +6301,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("grantUriPermission");
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6269,32 +6317,32 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("null uri");
}
- // Persistable only supported through Intents
- Preconditions.checkFlagsArgument(modeFlags,
- Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
- grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags,
- null);
+ grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags, null);
}
}
void removeUriPermissionIfNeededLocked(UriPermission perm) {
- if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
- |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
- ArrayMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.get(perm.targetUid);
+ if (perm.modeFlags == 0) {
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+ perm.targetUid);
if (perms != null) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Removing " + perm.targetUid + " permission to " + perm.uri);
+
perms.remove(perm.uri);
- if (perms.size() == 0) {
+ if (perms.isEmpty()) {
mGrantedUriPermissions.remove(perm.targetUid);
}
}
}
}
- private void revokeUriPermissionLocked(int callingUid, Uri uri, int modeFlags) {
+ private void revokeUriPermissionLocked(int callingUid, Uri uri, final int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + uri);
final IPackageManager pm = AppGlobals.getPackageManager();
@@ -6318,46 +6366,29 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean persistChanged = false;
// Go through all of the permissions and remove any that match.
- final List<String> SEGMENTS = uri.getPathSegments();
- if (SEGMENTS != null) {
- final int NS = SEGMENTS.size();
- int N = mGrantedUriPermissions.size();
- for (int i=0; i<N; i++) {
- ArrayMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.valueAt(i);
- Iterator<UriPermission> it = perms.values().iterator();
- toploop:
- while (it.hasNext()) {
- UriPermission perm = it.next();
- Uri targetUri = perm.uri;
- if (!authority.equals(targetUri.getAuthority())) {
- continue;
- }
- List<String> targetSegments = targetUri.getPathSegments();
- if (targetSegments == null) {
- continue;
- }
- if (targetSegments.size() < NS) {
- continue;
- }
- for (int j=0; j<NS; j++) {
- if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
- continue toploop;
- }
- }
- if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Revoking " + perm.targetUid + " permission to " + perm.uri);
- persistChanged |= perm.clearModes(modeFlags, true);
+ int N = mGrantedUriPermissions.size();
+ for (int i = 0; i < N; i++) {
+ final int targetUid = mGrantedUriPermissions.keyAt(i);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
+ for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
+ final UriPermission perm = it.next();
+ if (perm.uri.uri.isPathPrefixMatch(uri)) {
+ if (DEBUG_URI_PERMISSION)
+ Slog.v(TAG,
+ "Revoking " + perm.targetUid + " permission to " + perm.uri);
+ persistChanged |= perm.revokeModes(
+ modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
if (perm.modeFlags == 0) {
it.remove();
}
}
- if (perms.size() == 0) {
- mGrantedUriPermissions.remove(
- mGrantedUriPermissions.keyAt(i));
- N--;
- i--;
- }
+ }
+
+ if (perms.isEmpty()) {
+ mGrantedUriPermissions.remove(targetUid);
+ N--;
+ i--;
}
}
@@ -6368,7 +6399,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int modeFlags) {
+ final int modeFlags) {
enforceNotIsolatedCaller("revokeUriPermission");
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6382,9 +6413,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
- modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- if (modeFlags == 0) {
+ if (!Intent.isAccessUriMode(modeFlags)) {
return;
}
@@ -6419,20 +6448,22 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean persistChanged = false;
- final int size = mGrantedUriPermissions.size();
- for (int i = 0; i < size; i++) {
+ int N = mGrantedUriPermissions.size();
+ for (int i = 0; i < N; i++) {
+ final int targetUid = mGrantedUriPermissions.keyAt(i);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
// Only inspect grants matching user
if (userHandle == UserHandle.USER_ALL
- || userHandle == UserHandle.getUserId(mGrantedUriPermissions.keyAt(i))) {
- final Iterator<UriPermission> it = mGrantedUriPermissions.valueAt(i)
- .values().iterator();
- while (it.hasNext()) {
+ || userHandle == UserHandle.getUserId(targetUid)) {
+ for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
final UriPermission perm = it.next();
// Only inspect grants matching package
if (packageName == null || perm.sourcePkg.equals(packageName)
|| perm.targetPkg.equals(packageName)) {
- persistChanged |= perm.clearModes(~0, persistable);
+ persistChanged |= perm.revokeModes(
+ persistable ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
// Only remove when no modes remain; any persisted grants
// will keep this alive.
@@ -6441,6 +6472,12 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
}
+
+ if (perms.isEmpty()) {
+ mGrantedUriPermissions.remove(targetUid);
+ N--;
+ i--;
+ }
}
}
@@ -6460,7 +6497,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, final int modeFlags) {
synchronized(this) {
UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
@@ -6514,8 +6551,9 @@ public final class ActivityManagerService extends ActivityManagerNative
ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
synchronized (this) {
final int size = mGrantedUriPermissions.size();
- for (int i = 0 ; i < size; i++) {
- for (UriPermission perm : mGrantedUriPermissions.valueAt(i).values()) {
+ for (int i = 0; i < size; i++) {
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+ for (UriPermission perm : perms.values()) {
if (perm.persistedModeFlags != 0) {
persist.add(perm.snapshot());
}
@@ -6536,7 +6574,8 @@ public final class ActivityManagerService extends ActivityManagerNative
writeIntAttribute(out, ATTR_USER_HANDLE, perm.userHandle);
out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
- out.attribute(null, ATTR_URI, String.valueOf(perm.uri));
+ out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
+ writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix);
writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags);
writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime);
out.endTag(null, TAG_URI_GRANT);
@@ -6572,6 +6611,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
+ final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX);
final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS);
final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now);
@@ -6587,7 +6627,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (targetUid != -1) {
final UriPermission perm = findOrCreateUriPermissionLocked(
- sourcePkg, targetPkg, targetUid, uri);
+ sourcePkg, targetPkg, targetUid, new GrantUri(uri, prefix));
perm.initPersistedModes(modeFlags, createdTime);
}
} else {
@@ -6609,7 +6649,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void takePersistableUriPermission(Uri uri, int modeFlags) {
+ public void takePersistableUriPermission(Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("takePersistableUriPermission");
Preconditions.checkFlagsArgument(modeFlags,
@@ -6617,13 +6657,28 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
final int callingUid = Binder.getCallingUid();
- final UriPermission perm = findUriPermissionLocked(callingUid, uri);
- if (perm == null) {
- throw new SecurityException("No permission grant found for UID " + callingUid
- + " and Uri " + uri.toSafeString());
+ boolean persistChanged = false;
+
+ UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
+ UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+
+ final boolean exactValid = (exactPerm != null)
+ && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
+ final boolean prefixValid = (prefixPerm != null)
+ && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags);
+
+ if (!(exactValid || prefixValid)) {
+ throw new SecurityException("No persistable permission grants found for UID "
+ + callingUid + " and Uri " + uri.toSafeString());
+ }
+
+ if (exactValid) {
+ persistChanged |= exactPerm.takePersistableModes(modeFlags);
+ }
+ if (prefixValid) {
+ persistChanged |= prefixPerm.takePersistableModes(modeFlags);
}
- boolean persistChanged = perm.takePersistableModes(modeFlags);
persistChanged |= maybePrunePersistedUriGrantsLocked(callingUid);
if (persistChanged) {
@@ -6633,7 +6688,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void releasePersistableUriPermission(Uri uri, int modeFlags) {
+ public void releasePersistableUriPermission(Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("releasePersistableUriPermission");
Preconditions.checkFlagsArgument(modeFlags,
@@ -6641,16 +6696,24 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
final int callingUid = Binder.getCallingUid();
+ boolean persistChanged = false;
- final UriPermission perm = findUriPermissionLocked(callingUid, uri);
- if (perm == null) {
- Slog.w(TAG, "No permission grant found for UID " + callingUid + " and Uri "
- + uri.toSafeString());
- return;
+ UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
+ UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+ if (exactPerm == null && prefixPerm == null) {
+ throw new SecurityException("No permission grants found for UID " + callingUid
+ + " and Uri " + uri.toSafeString());
+ }
+
+ if (exactPerm != null) {
+ persistChanged |= exactPerm.releasePersistableModes(modeFlags);
+ removeUriPermissionIfNeededLocked(exactPerm);
+ }
+ if (prefixPerm != null) {
+ persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
+ removeUriPermissionIfNeededLocked(prefixPerm);
}
- final boolean persistChanged = perm.releasePersistableModes(modeFlags);
- removeUriPermissionIfNeededLocked(perm);
if (persistChanged) {
schedulePersistUriGrants();
}
@@ -6664,7 +6727,7 @@ public final class ActivityManagerService extends ActivityManagerNative
* @return if any mutations occured that require persisting.
*/
private boolean maybePrunePersistedUriGrantsLocked(int uid) {
- final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
if (perms == null) return false;
if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
@@ -6714,13 +6777,12 @@ public final class ActivityManagerService extends ActivityManagerNative
final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
synchronized (this) {
if (incoming) {
- final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+ callingUid);
if (perms == null) {
Slog.w(TAG, "No permission grants found for " + packageName);
} else {
- final int size = perms.size();
- for (int i = 0; i < size; i++) {
- final UriPermission perm = perms.valueAt(i);
+ for (UriPermission perm : perms.values()) {
if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
result.add(perm.buildPersistedPublicApiObject());
}
@@ -6729,10 +6791,9 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
final int size = mGrantedUriPermissions.size();
for (int i = 0; i < size; i++) {
- final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
- final int permsSize = perms.size();
- for (int j = 0; j < permsSize; j++) {
- final UriPermission perm = perms.valueAt(j);
+ final ArrayMap<GrantUri, UriPermission> perms =
+ mGrantedUriPermissions.valueAt(i);
+ for (UriPermission perm : perms.values()) {
if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
result.add(perm.buildPersistedPublicApiObject());
}
@@ -7602,11 +7663,11 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
}
-
- ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
if (perms != null) {
- for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
- if (uri.getKey().getAuthority().equals(cpi.authority)) {
+ for (GrantUri uri : perms.keySet()) {
+ if (uri.uri.getAuthority().equals(cpi.authority)) {
return null;
}
}
@@ -11573,8 +11634,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
continue;
}
- ArrayMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.valueAt(i);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
if (!printed) {
if (needSep) pw.println();
needSep = true;
@@ -11582,8 +11642,7 @@ public final class ActivityManagerService extends ActivityManagerNative
printed = true;
printedAnything = true;
}
- pw.print(" * UID "); pw.print(uid);
- pw.println(" holds:");
+ pw.print(" * UID "); pw.print(uid); pw.println(" holds:");
for (UriPermission perm : perms.values()) {
pw.print(" "); pw.println(perm);
if (dumpAll) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 60adfb0..3e59def 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -215,14 +215,7 @@ final class ActivityRecord {
pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
}
if (uriPermissions != null) {
- if (uriPermissions.readUriPermissions != null) {
- pw.print(prefix); pw.print("readUriPermissions=");
- pw.println(uriPermissions.readUriPermissions);
- }
- if (uriPermissions.writeUriPermissions != null) {
- pw.print(prefix); pw.print("writeUriPermissions=");
- pw.println(uriPermissions.writeUriPermissions);
- }
+ uriPermissions.dump(pw, prefix);
}
pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
pw.print(" launchCount="); pw.print(launchCount);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 363a9b7..e54c95e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -193,14 +193,7 @@ final class ServiceRecord extends Binder {
pw.println(si.neededGrants);
}
if (si.uriPermissions != null) {
- if (si.uriPermissions.readUriPermissions != null) {
- pw.print(prefix); pw.print(" readUriPermissions=");
- pw.println(si.uriPermissions.readUriPermissions);
- }
- if (si.uriPermissions.writeUriPermissions != null) {
- pw.print(prefix); pw.print(" writeUriPermissions=");
- pw.println(si.uriPermissions.writeUriPermissions);
- }
+ si.uriPermissions.dump(pw, prefix);
}
}
}
diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
index 1f12b74..4970b8d 100644
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ b/services/core/java/com/android/server/am/UriPermission.java
@@ -17,15 +17,16 @@
package com.android.server.am;
import android.content.Intent;
-import android.net.Uri;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.Log;
+import android.util.Slog;
+import com.android.server.am.ActivityManagerService.GrantUri;
import com.google.android.collect.Sets;
import java.io.PrintWriter;
import java.util.Comparator;
-import java.util.HashSet;
/**
* Description of a permission granted to an app to access a particular URI.
@@ -50,7 +51,7 @@ final class UriPermission {
/** Cached UID of {@link #targetPkg}; should not be persisted */
final int targetUid;
- final Uri uri;
+ final GrantUri uri;
/**
* Allowed modes. All permission enforcement should use this field. Must
@@ -61,12 +62,13 @@ final class UriPermission {
*/
int modeFlags = 0;
- /** Allowed modes with explicit owner. */
+ /** Allowed modes with active owner. */
int ownedModeFlags = 0;
/** Allowed modes without explicit owner. */
int globalModeFlags = 0;
/** Allowed modes that have been offered for possible persisting. */
int persistableModeFlags = 0;
+
/** Allowed modes that should be persisted across device boots. */
int persistedModeFlags = 0;
@@ -78,12 +80,12 @@ final class UriPermission {
private static final long INVALID_TIME = Long.MIN_VALUE;
- private HashSet<UriPermissionOwner> mReadOwners;
- private HashSet<UriPermissionOwner> mWriteOwners;
+ private ArraySet<UriPermissionOwner> mReadOwners;
+ private ArraySet<UriPermissionOwner> mWriteOwners;
private String stringName;
- UriPermission(String sourcePkg, String targetPkg, int targetUid, Uri uri) {
+ UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
this.userHandle = UserHandle.getUserId(targetUid);
this.sourcePkg = sourcePkg;
this.targetPkg = targetPkg;
@@ -100,6 +102,9 @@ final class UriPermission {
* global or owner grants.
*/
void initPersistedModes(int modeFlags, long createdTime) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
persistableModeFlags = modeFlags;
persistedModeFlags = modeFlags;
persistedCreateTime = createdTime;
@@ -107,7 +112,11 @@ final class UriPermission {
updateModeFlags();
}
- void grantModes(int modeFlags, boolean persistable, UriPermissionOwner owner) {
+ void grantModes(int modeFlags, UriPermissionOwner owner) {
+ final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
if (persistable) {
persistableModeFlags |= modeFlags;
}
@@ -130,10 +139,14 @@ final class UriPermission {
* @return if mode changes should trigger persisting.
*/
boolean takePersistableModes(int modeFlags) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
if ((modeFlags & persistableModeFlags) != modeFlags) {
- throw new SecurityException("Requested flags 0x"
+ Slog.w(TAG, "Requested flags 0x"
+ Integer.toHexString(modeFlags) + ", but only 0x"
+ Integer.toHexString(persistableModeFlags) + " are allowed");
+ return false;
}
final int before = persistedModeFlags;
@@ -148,6 +161,9 @@ final class UriPermission {
}
boolean releasePersistableModes(int modeFlags) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
final int before = persistedModeFlags;
persistableModeFlags &= ~modeFlags;
@@ -164,7 +180,11 @@ final class UriPermission {
/**
* @return if mode changes should trigger persisting.
*/
- boolean clearModes(int modeFlags, boolean persistable) {
+ boolean revokeModes(int modeFlags) {
+ final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
final int before = persistedModeFlags;
if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
@@ -208,6 +228,8 @@ final class UriPermission {
* Return strength of this permission grant for the given flags.
*/
public int getStrength(int modeFlags) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if ((persistableModeFlags & modeFlags) == modeFlags) {
return STRENGTH_PERSISTABLE;
} else if ((globalModeFlags & modeFlags) == modeFlags) {
@@ -221,7 +243,7 @@ final class UriPermission {
private void addReadOwner(UriPermissionOwner owner) {
if (mReadOwners == null) {
- mReadOwners = Sets.newHashSet();
+ mReadOwners = Sets.newArraySet();
ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
updateModeFlags();
}
@@ -246,7 +268,7 @@ final class UriPermission {
private void addWriteOwner(UriPermissionOwner owner) {
if (mWriteOwners == null) {
- mWriteOwners = Sets.newHashSet();
+ mWriteOwners = Sets.newArraySet();
ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
updateModeFlags();
}
@@ -333,7 +355,7 @@ final class UriPermission {
final int userHandle;
final String sourcePkg;
final String targetPkg;
- final Uri uri;
+ final GrantUri uri;
final int persistedModeFlags;
final long persistedCreateTime;
@@ -352,6 +374,6 @@ final class UriPermission {
}
public android.content.UriPermission buildPersistedPublicApiObject() {
- return new android.content.UriPermission(uri, persistedModeFlags, persistedCreateTime);
+ return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
}
}
diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
index 7bbd3bc..65d7047 100644
--- a/services/core/java/com/android/server/am/UriPermissionOwner.java
+++ b/services/core/java/com/android/server/am/UriPermissionOwner.java
@@ -20,8 +20,11 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
+import android.util.ArraySet;
-import java.util.HashSet;
+import com.google.android.collect.Sets;
+
+import java.io.PrintWriter;
import java.util.Iterator;
final class UriPermissionOwner {
@@ -30,8 +33,8 @@ final class UriPermissionOwner {
Binder externalToken;
- HashSet<UriPermission> readUriPermissions; // special access to reading uris.
- HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+ private ArraySet<UriPermission> mReadPerms;
+ private ArraySet<UriPermission> mWritePerms;
class ExternalToken extends Binder {
UriPermissionOwner getOwner() {
@@ -39,9 +42,9 @@ final class UriPermissionOwner {
}
}
- UriPermissionOwner(ActivityManagerService _service, Object _owner) {
- service = _service;
- owner = _owner;
+ UriPermissionOwner(ActivityManagerService service, Object owner) {
+ this.service = service;
+ this.owner = owner;
}
Binder getExternalTokenLocked() {
@@ -64,82 +67,76 @@ final class UriPermissionOwner {
}
void removeUriPermissionsLocked(int mode) {
- if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
- && readUriPermissions != null) {
- for (UriPermission perm : readUriPermissions) {
- perm.removeReadOwner(this);
- service.removeUriPermissionIfNeededLocked(perm);
- }
- readUriPermissions = null;
- }
- if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
- && writeUriPermissions != null) {
- for (UriPermission perm : writeUriPermissions) {
- perm.removeWriteOwner(this);
- service.removeUriPermissionIfNeededLocked(perm);
- }
- writeUriPermissions = null;
- }
+ removeUriPermissionLocked(null, mode);
}
void removeUriPermissionLocked(Uri uri, int mode) {
- if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
- && readUriPermissions != null) {
- Iterator<UriPermission> it = readUriPermissions.iterator();
+ if ((mode & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+ && mReadPerms != null) {
+ Iterator<UriPermission> it = mReadPerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (uri.equals(perm.uri)) {
+ if (uri == null || uri.equals(perm.uri)) {
perm.removeReadOwner(this);
service.removeUriPermissionIfNeededLocked(perm);
it.remove();
}
}
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
+ if (mReadPerms.isEmpty()) {
+ mReadPerms = null;
}
}
- if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
- && writeUriPermissions != null) {
- Iterator<UriPermission> it = writeUriPermissions.iterator();
+ if ((mode & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+ && mWritePerms != null) {
+ Iterator<UriPermission> it = mWritePerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (uri.equals(perm.uri)) {
+ if (uri == null || uri.equals(perm.uri)) {
perm.removeWriteOwner(this);
service.removeUriPermissionIfNeededLocked(perm);
it.remove();
}
}
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
+ if (mWritePerms.isEmpty()) {
+ mWritePerms = null;
}
}
}
public void addReadPermission(UriPermission perm) {
- if (readUriPermissions == null) {
- readUriPermissions = new HashSet<UriPermission>();
+ if (mReadPerms == null) {
+ mReadPerms = Sets.newArraySet();
}
- readUriPermissions.add(perm);
+ mReadPerms.add(perm);
}
public void addWritePermission(UriPermission perm) {
- if (writeUriPermissions == null) {
- writeUriPermissions = new HashSet<UriPermission>();
+ if (mWritePerms == null) {
+ mWritePerms = Sets.newArraySet();
}
- writeUriPermissions.add(perm);
+ mWritePerms.add(perm);
}
public void removeReadPermission(UriPermission perm) {
- readUriPermissions.remove(perm);
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
+ mReadPerms.remove(perm);
+ if (mReadPerms.isEmpty()) {
+ mReadPerms = null;
}
}
public void removeWritePermission(UriPermission perm) {
- writeUriPermissions.remove(perm);
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
+ mWritePerms.remove(perm);
+ if (mWritePerms.isEmpty()) {
+ mWritePerms = null;
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ if (mReadPerms != null) {
+ pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms);
+ }
+ if (mWritePerms != null) {
+ pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms);
}
}