summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-08-25 22:00:28 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-08-25 22:00:28 -0700
commit3003a017d312a55e3804d6cf4a80044b1f1d7993 (patch)
treebfd0910b8bde42c17967399981b5a347069eae18 /services
parent14e00621c81da6a0391da47afce77945b27c7231 (diff)
parent7e269644fcc319835f1e7f762f3cbd8087e3e22f (diff)
downloadframeworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.zip
frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.tar.gz
frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.tar.bz2
Merge "Don't retain global ref to last inflated context." into gingerbread
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java58
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java84
-rw-r--r--services/java/com/android/server/am/ActivityStack.java8
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java81
-rw-r--r--services/java/com/android/server/am/UriPermission.java15
-rw-r--r--services/java/com/android/server/am/UriPermissionOwner.java166
6 files changed, 272 insertions, 140 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c316074..d535343 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4294,12 +4294,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
+ " when granting permission to uri " + uri);
}
if (targetPkg == null) {
- Slog.w(TAG, "grantUriPermission: null target");
- return;
+ throw new IllegalArgumentException("null target");
}
if (uri == null) {
- Slog.w(TAG, "grantUriPermission: null uri");
- return;
+ throw new IllegalArgumentException("null uri");
}
grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
@@ -4451,6 +4449,56 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ @Override
+ public IBinder newUriPermissionOwner(String name) {
+ synchronized(this) {
+ UriPermissionOwner owner = new UriPermissionOwner(this, name);
+ return owner.getExternalTokenLocked();
+ }
+ }
+
+ @Override
+ public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
+ Uri uri, int modeFlags) {
+ synchronized(this) {
+ UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+ if (owner == null) {
+ throw new IllegalArgumentException("Unknown owner: " + token);
+ }
+ if (fromUid != Binder.getCallingUid()) {
+ if (Binder.getCallingUid() != Process.myUid()) {
+ // Only system code can grant URI permissions on behalf
+ // of other users.
+ throw new SecurityException("nice try");
+ }
+ }
+ if (targetPkg == null) {
+ throw new IllegalArgumentException("null target");
+ }
+ if (uri == null) {
+ throw new IllegalArgumentException("null uri");
+ }
+
+ grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
+ }
+ }
+
+ @Override
+ public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
+ synchronized(this) {
+ UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+ if (owner == null) {
+ throw new IllegalArgumentException("Unknown owner: " + token);
+ }
+
+ if (uri == null) {
+ owner.removeUriPermissionsLocked(mode);
+ } else {
+ owner.removeUriPermissionLocked(uri, mode);
+ }
+ }
+ }
+
public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
synchronized (this) {
ProcessRecord app =
@@ -8260,7 +8308,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
si.deliveryCount++;
if (si.targetPermissionUid >= 0) {
grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
- r.packageName, si.intent, si);
+ r.packageName, si.intent, si.getUriPermissionsLocked());
}
if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
bumpServiceExecutingLocked(r);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 80a41b7..62be918 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -44,7 +44,7 @@ import java.util.HashSet;
/**
* An entry in the history stack, representing an activity.
*/
-class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner {
+class ActivityRecord extends IApplicationToken.Stub {
final ActivityManagerService service; // owner
final ActivityStack stack; // owner
final ActivityInfo info; // all about me
@@ -78,8 +78,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne
HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
ArrayList newIntents; // any pending new intents for single-top mode
HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
- HashSet<UriPermission> readUriPermissions; // special access to reading uris.
- HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+ UriPermissionOwner uriPermissions; // current special URI access perms.
ProcessRecord app; // if non-null, hosting application
Bitmap thumbnail; // icon representation of paused screen
CharSequence description; // textual description of paused screen
@@ -141,11 +140,15 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne
if (pendingResults != null) {
pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
}
- if (readUriPermissions != null) {
- pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
- }
- if (writeUriPermissions != null) {
- pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
+ 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);
+ }
}
pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
pw.print(" haveState="); pw.print(haveState);
@@ -301,6 +304,13 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne
}
}
+ UriPermissionOwner getUriPermissionsLocked() {
+ if (uriPermissions == null) {
+ uriPermissions = new UriPermissionOwner(service, this);
+ }
+ return uriPermissions;
+ }
+
void addResultLocked(ActivityRecord from, String resultWho,
int requestCode, int resultCode,
Intent resultData) {
@@ -350,7 +360,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne
intent = new Intent(intent);
ar.add(intent);
service.grantUriPermissionFromIntentLocked(callingUid, packageName,
- intent, this);
+ intent, getUriPermissionsLocked());
app.thread.scheduleNewIntent(ar, this);
sent = true;
} catch (RemoteException e) {
@@ -367,27 +377,9 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne
}
void removeUriPermissionsLocked() {
- if (readUriPermissions != null) {
- for (UriPermission perm : readUriPermissions) {
- perm.readOwners.remove(this);
- if (perm.readOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
- service.removeUriPermissionIfNeededLocked(perm);
- }
- }
- readUriPermissions = null;
- }
- if (writeUriPermissions != null) {
- for (UriPermission perm : writeUriPermissions) {
- perm.writeOwners.remove(this);
- if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- service.removeUriPermissionIfNeededLocked(perm);
- }
- }
- writeUriPermissions = null;
+ if (uriPermissions != null) {
+ uriPermissions.removeUriPermissionsLocked();
+ uriPermissions = null;
}
}
@@ -578,38 +570,6 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne
state == ActivityState.RESUMED;
}
- @Override
- public void addReadPermission(UriPermission perm) {
- if (readUriPermissions == null) {
- readUriPermissions = new HashSet<UriPermission>();
- }
- readUriPermissions.add(perm);
- }
-
- @Override
- public void addWritePermission(UriPermission perm) {
- if (writeUriPermissions == null) {
- writeUriPermissions = new HashSet<UriPermission>();
- }
- writeUriPermissions.add(perm);
- }
-
- @Override
- public void removeReadPermission(UriPermission perm) {
- readUriPermissions.remove(perm);
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
- }
- }
-
- @Override
- public void removeWritePermission(UriPermission perm) {
- writeUriPermissions.remove(perm);
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
- }
- }
-
public String toString() {
if (stringName != null) {
return stringName;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a5f7e96..a99b48c 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2327,12 +2327,12 @@ public class ActivityStack {
if (grantedUriPermissions != null && callingUid > 0) {
for (int i=0; i<grantedUriPermissions.length; i++) {
mService.grantUriPermissionLocked(callingUid, r.packageName,
- grantedUriPermissions[i], grantedMode, r);
+ grantedUriPermissions[i], grantedMode, r.getUriPermissionsLocked());
}
}
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
- intent, r);
+ intent, r.getUriPermissionsLocked());
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
@@ -2557,7 +2557,7 @@ public class ActivityStack {
if (callingUid > 0) {
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
- data, r);
+ data, r.getUriPermissionsLocked());
}
if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
@@ -2885,7 +2885,7 @@ public class ActivityStack {
+ " res=" + resultCode + " data=" + resultData);
if (r.info.applicationInfo.uid > 0) {
mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
- r.packageName, resultData, r);
+ r.packageName, resultData, r.getUriPermissionsLocked());
}
resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
resultData);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index d5b050b..f35a68e 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -96,7 +96,7 @@ class ServiceRecord extends Binder {
String stringName; // caching of toString
- static class StartItem implements UriPermissionOwner {
+ static class StartItem {
final ServiceRecord sr;
final int id;
final Intent intent;
@@ -104,12 +104,10 @@ class ServiceRecord extends Binder {
long deliveredTime;
int deliveryCount;
int doneExecutingCount;
+ UriPermissionOwner uriPermissions;
String stringName; // caching of toString
- HashSet<UriPermission> readUriPermissions; // special access to reading uris.
- HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
-
StartItem(ServiceRecord _sr, int _id, Intent _intent, int _targetPermissionUid) {
sr = _sr;
id = _id;
@@ -117,60 +115,17 @@ class ServiceRecord extends Binder {
targetPermissionUid = _targetPermissionUid;
}
- void removeUriPermissionsLocked() {
- if (readUriPermissions != null) {
- for (UriPermission perm : readUriPermissions) {
- perm.readOwners.remove(this);
- if (perm.readOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
- sr.ams.removeUriPermissionIfNeededLocked(perm);
- }
- }
- readUriPermissions = null;
- }
- if (writeUriPermissions != null) {
- for (UriPermission perm : writeUriPermissions) {
- perm.writeOwners.remove(this);
- if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- sr.ams.removeUriPermissionIfNeededLocked(perm);
- }
- }
- writeUriPermissions = null;
- }
- }
-
- @Override
- public void addReadPermission(UriPermission perm) {
- if (readUriPermissions == null) {
- readUriPermissions = new HashSet<UriPermission>();
+ UriPermissionOwner getUriPermissionsLocked() {
+ if (uriPermissions == null) {
+ uriPermissions = new UriPermissionOwner(sr.ams, this);
}
- readUriPermissions.add(perm);
+ return uriPermissions;
}
- @Override
- public void addWritePermission(UriPermission perm) {
- if (writeUriPermissions == null) {
- writeUriPermissions = new HashSet<UriPermission>();
- }
- writeUriPermissions.add(perm);
- }
-
- @Override
- public void removeReadPermission(UriPermission perm) {
- readUriPermissions.remove(perm);
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
- }
- }
-
- @Override
- public void removeWritePermission(UriPermission perm) {
- writeUriPermissions.remove(perm);
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
+ void removeUriPermissionsLocked() {
+ if (uriPermissions != null) {
+ uriPermissions.removeUriPermissionsLocked();
+ uriPermissions = null;
}
}
@@ -218,13 +173,15 @@ class ServiceRecord extends Binder {
pw.print(prefix); pw.print(" targetPermissionUid=");
pw.println(si.targetPermissionUid);
}
- if (si.readUriPermissions != null) {
- pw.print(prefix); pw.print(" readUriPermissions=");
- pw.println(si.readUriPermissions);
- }
- if (si.writeUriPermissions != null) {
- pw.print(prefix); pw.print(" writeUriPermissions=");
- pw.println(si.writeUriPermissions);
+ 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);
+ }
}
}
}
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index 93c59cc..c95546e 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -22,13 +22,14 @@ import android.net.Uri;
import java.io.PrintWriter;
import java.util.HashSet;
-interface UriPermissionOwner {
- void addReadPermission(UriPermission perm);
- void addWritePermission(UriPermission perm);
- void removeReadPermission(UriPermission perm);
- void removeWritePermission(UriPermission perm);
-}
-
+/**
+ * Description of a permission granted to an app to access a particular URI.
+ *
+ * CTS tests for this functionality can be run with "runtest cts-appsecurity".
+ *
+ * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert
+ * /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+ */
class UriPermission {
final int uid;
final Uri uri;
diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/java/com/android/server/am/UriPermissionOwner.java
new file mode 100644
index 0000000..99c82e6
--- /dev/null
+++ b/services/java/com/android/server/am/UriPermissionOwner.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+class UriPermissionOwner {
+ final ActivityManagerService service;
+ final Object owner;
+
+ Binder externalToken;
+
+ HashSet<UriPermission> readUriPermissions; // special access to reading uris.
+ HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+
+ class ExternalToken extends Binder {
+ UriPermissionOwner getOwner() {
+ return UriPermissionOwner.this;
+ }
+ }
+
+ UriPermissionOwner(ActivityManagerService _service, Object _owner) {
+ service = _service;
+ owner = _owner;
+ }
+
+ Binder getExternalTokenLocked() {
+ if (externalToken != null) {
+ externalToken = new ExternalToken();
+ }
+ return externalToken;
+ }
+
+ static UriPermissionOwner fromExternalToken(IBinder token) {
+ if (token instanceof ExternalToken) {
+ return ((ExternalToken)token).getOwner();
+ }
+ return null;
+ }
+
+ void removeUriPermissionsLocked() {
+ removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ }
+
+ void removeUriPermissionsLocked(int mode) {
+ if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+ && readUriPermissions != null) {
+ for (UriPermission perm : readUriPermissions) {
+ perm.readOwners.remove(this);
+ if (perm.readOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ }
+ readUriPermissions = null;
+ }
+ if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+ && writeUriPermissions != null) {
+ for (UriPermission perm : writeUriPermissions) {
+ perm.writeOwners.remove(this);
+ if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ }
+ writeUriPermissions = null;
+ }
+ }
+
+ void removeUriPermissionLocked(Uri uri, int mode) {
+ if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+ && readUriPermissions != null) {
+ Iterator<UriPermission> it = readUriPermissions.iterator();
+ while (it.hasNext()) {
+ UriPermission perm = it.next();
+ if (uri.equals(perm.uri)) {
+ perm.readOwners.remove(this);
+ if (perm.readOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ it.remove();
+ }
+ }
+ if (readUriPermissions.size() == 0) {
+ readUriPermissions = null;
+ }
+ }
+ if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+ && writeUriPermissions != null) {
+ Iterator<UriPermission> it = writeUriPermissions.iterator();
+ while (it.hasNext()) {
+ UriPermission perm = it.next();
+ if (uri.equals(perm.uri)) {
+ perm.writeOwners.remove(this);
+ if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ it.remove();
+ }
+ }
+ if (writeUriPermissions.size() == 0) {
+ writeUriPermissions = null;
+ }
+ }
+ }
+
+ public void addReadPermission(UriPermission perm) {
+ if (readUriPermissions == null) {
+ readUriPermissions = new HashSet<UriPermission>();
+ }
+ readUriPermissions.add(perm);
+ }
+
+ public void addWritePermission(UriPermission perm) {
+ if (writeUriPermissions == null) {
+ writeUriPermissions = new HashSet<UriPermission>();
+ }
+ writeUriPermissions.add(perm);
+ }
+
+ public void removeReadPermission(UriPermission perm) {
+ readUriPermissions.remove(perm);
+ if (readUriPermissions.size() == 0) {
+ readUriPermissions = null;
+ }
+ }
+
+ public void removeWritePermission(UriPermission perm) {
+ writeUriPermissions.remove(perm);
+ if (writeUriPermissions.size() == 0) {
+ writeUriPermissions = null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return owner.toString();
+ }
+}