summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2009-10-06 17:18:05 -0700
committerDianne Hackborn <hackbod@google.com>2009-10-07 11:10:33 -0700
commit0c3154d3fc54a1b3d8358a2932042cca729327b9 (patch)
tree55b34effec937b2a0bc7a7504d9df73268dcdc32 /services
parent4625758d0b909ccfc9f40b707666b1b21e9e8ffd (diff)
downloadframeworks_base-0c3154d3fc54a1b3d8358a2932042cca729327b9.zip
frameworks_base-0c3154d3fc54a1b3d8358a2932042cca729327b9.tar.gz
frameworks_base-0c3154d3fc54a1b3d8358a2932042cca729327b9.tar.bz2
Fix issue #2163654: deadlock, runtime restart
Don't hold a lock when the activity thread is telling the activity manager to release a provider. This requires that the activity manager now keep a reference count on the providers, because without the lock it is possible for activity thread to call in to request the provider again before it has finished telling about the release. Change-Id: I5f912903891f4edae85e28819d4e6f14b8f2e688
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java29
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java3
2 files changed, 24 insertions, 8 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 34302b1..c611795 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7542,8 +7542,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (DEBUG_PROVIDER) Log.v(TAG,
"Adding provider requested by "
+ r.processName + " from process "
- + cpr.info.processName);
- r.conProviders.add(cpr);
+ + cpr.info.processName);
+ Integer cnt = r.conProviders.get(cpr);
+ if (cnt == null) {
+ r.conProviders.put(cpr, new Integer(1));
+ } else {
+ r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
+ }
cpr.clients.add(r);
} else {
cpr.externals++;
@@ -7648,8 +7653,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (DEBUG_PROVIDER) Log.v(TAG,
"Adding provider requested by "
+ r.processName + " from process "
- + cpr.info.processName);
- r.conProviders.add(cpr);
+ + cpr.info.processName);
+ Integer cnt = r.conProviders.get(cpr);
+ if (cnt == null) {
+ r.conProviders.put(cpr, new Integer(1));
+ } else {
+ r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
+ }
cpr.clients.add(r);
} else {
cpr.externals++;
@@ -7726,8 +7736,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
+ cpr.info.name + " in process " + r.processName);
return;
} else {
- localCpr.clients.remove(r);
- r.conProviders.remove(localCpr);
+ Integer cnt = r.conProviders.get(localCpr);
+ if (cnt == null || cnt.intValue() <= 1) {
+ localCpr.clients.remove(r);
+ r.conProviders.remove(localCpr);
+ } else {
+ r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
+ }
}
updateOomAdjLocked();
}
@@ -9914,7 +9929,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// Unregister from connected content providers.
if (!app.conProviders.isEmpty()) {
- Iterator it = app.conProviders.iterator();
+ Iterator it = app.conProviders.keySet().iterator();
while (it.hasNext()) {
ContentProviderRecord cpr = (ContentProviderRecord)it.next();
cpr.clients.remove(app);
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index d05b44b..6202257 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -94,7 +94,8 @@ class ProcessRecord implements Watchdog.PssRequestor {
// class (String) -> ContentProviderRecord
final HashMap pubProviders = new HashMap();
// All ContentProviderRecord process is using
- final HashSet conProviders = new HashSet();
+ final HashMap<ContentProviderRecord, Integer> conProviders
+ = new HashMap<ContentProviderRecord, Integer>();
boolean persistent; // always keep this application running?
boolean crashing; // are we in the process of crashing?