summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2015-02-03 18:41:12 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-02-03 18:41:14 +0000
commit53e8d6f934be403b9c7733c190b6052d60dd0658 (patch)
tree62e258eea526323d917d79d2882d53e0b8ffb8b1 /services
parent240e8743977d1a1e7a43ff42e0d52148db10cda8 (diff)
parent9ac9609f4d078dc0d7fe7c703fb88d20fd629bfe (diff)
downloadframeworks_base-53e8d6f934be403b9c7733c190b6052d60dd0658.zip
frameworks_base-53e8d6f934be403b9c7733c190b6052d60dd0658.tar.gz
frameworks_base-53e8d6f934be403b9c7733c190b6052d60dd0658.tar.bz2
Merge "[ActivityManager] Prevent application holding AMS lock"
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java102
1 files changed, 53 insertions, 49 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f7d6e8a..91736f3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15155,30 +15155,6 @@ public final class ActivityManagerService extends ActivityManagerNative
// BROADCASTS
// =========================================================
- private final List getStickiesLocked(String action, IntentFilter filter,
- List cur, int userId) {
- final ContentResolver resolver = mContext.getContentResolver();
- ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
- if (stickies == null) {
- return cur;
- }
- final ArrayList<Intent> list = stickies.get(action);
- if (list == null) {
- return cur;
- }
- int N = list.size();
- for (int i=0; i<N; i++) {
- Intent intent = list.get(i);
- if (filter.match(resolver, intent, true, TAG) >= 0) {
- if (cur == null) {
- cur = new ArrayList<Intent>();
- }
- cur.add(intent);
- }
- }
- return cur;
- }
-
boolean isPendingBroadcastProcessLocked(int pid) {
return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
|| mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid);
@@ -15203,10 +15179,11 @@ public final class ActivityManagerService extends ActivityManagerNative
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
enforceNotIsolatedCaller("registerReceiver");
+ ArrayList<Intent> stickyIntents = null;
+ ProcessRecord callerApp = null;
int callingUid;
int callingPid;
synchronized(this) {
- ProcessRecord callerApp = null;
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
@@ -15229,39 +15206,66 @@ public final class ActivityManagerService extends ActivityManagerNative
callingPid = Binder.getCallingPid();
}
- userId = this.handleIncomingUser(callingPid, callingUid, userId,
+ userId = handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
- List allSticky = null;
+ Iterator<String> actions = filter.actionsIterator();
+ if (actions == null) {
+ ArrayList<String> noAction = new ArrayList<String>(1);
+ noAction.add(null);
+ actions = noAction.iterator();
+ }
+
+ // Collect stickies of users
+ int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
+ while (actions.hasNext()) {
+ String action = actions.next();
+ for (int id : userIds) {
+ ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
+ if (stickies != null) {
+ ArrayList<Intent> intents = stickies.get(action);
+ if (intents != null) {
+ if (stickyIntents == null) {
+ stickyIntents = new ArrayList<Intent>();
+ }
+ stickyIntents.addAll(intents);
+ }
+ }
+ }
+ }
+ }
+ ArrayList<Intent> allSticky = null;
+ if (stickyIntents != null) {
+ final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
- Iterator actions = filter.actionsIterator();
- if (actions != null) {
- while (actions.hasNext()) {
- String action = (String)actions.next();
- allSticky = getStickiesLocked(action, filter, allSticky,
- UserHandle.USER_ALL);
- allSticky = getStickiesLocked(action, filter, allSticky,
- UserHandle.getUserId(callingUid));
+ for (int i = 0, N = stickyIntents.size(); i < N; i++) {
+ Intent intent = stickyIntents.get(i);
+ // If intent has scheme "content", it will need to acccess
+ // provider that needs to lock mProviderMap in ActivityThread
+ // and also it may need to wait application response, so we
+ // cannot lock ActivityManagerService here.
+ if (filter.match(resolver, intent, true, TAG) >= 0) {
+ if (allSticky == null) {
+ allSticky = new ArrayList<Intent>();
+ }
+ allSticky.add(intent);
}
- } else {
- allSticky = getStickiesLocked(null, filter, allSticky,
- UserHandle.USER_ALL);
- allSticky = getStickiesLocked(null, filter, allSticky,
- UserHandle.getUserId(callingUid));
}
+ }
- // The first sticky in the list is returned directly back to
- // the client.
- Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
-
- if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
- + ": " + sticky);
+ // The first sticky in the list is returned directly back to the client.
+ Intent sticky = allSticky != null ? allSticky.get(0) : null;
+ if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter + ": " + sticky);
+ if (receiver == null) {
+ return sticky;
+ }
- if (receiver == null) {
- return sticky;
+ synchronized (this) {
+ if (callerApp != null && callerApp.pid == 0) {
+ // Caller already died
+ return null;
}
-
ReceiverList rl
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {