diff options
author | Craig Mautner <cmautner@google.com> | 2015-02-03 18:41:12 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-02-03 18:41:14 +0000 |
commit | 53e8d6f934be403b9c7733c190b6052d60dd0658 (patch) | |
tree | 62e258eea526323d917d79d2882d53e0b8ffb8b1 /services | |
parent | 240e8743977d1a1e7a43ff42e0d52148db10cda8 (diff) | |
parent | 9ac9609f4d078dc0d7fe7c703fb88d20fd629bfe (diff) | |
download | frameworks_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.java | 102 |
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) { |