summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/am/ActivityManagerService.java
diff options
context:
space:
mode:
authorRobert Carr <racarr@google.com>2015-09-17 10:54:58 -0700
committerRob Carr <racarr@google.com>2015-09-21 18:03:50 +0000
commit64b5e1c4f9991cbd97050bd3f183bf510fce2077 (patch)
treec54970912c9f3b53ae1d10a4c4c0141d5b60fa8e /services/core/java/com/android/server/am/ActivityManagerService.java
parent7aa79efe80b790eef61ac355c0ce6c7b606e6f78 (diff)
downloadframeworks_base-64b5e1c4f9991cbd97050bd3f183bf510fce2077.zip
frameworks_base-64b5e1c4f9991cbd97050bd3f183bf510fce2077.tar.gz
frameworks_base-64b5e1c4f9991cbd97050bd3f183bf510fce2077.tar.bz2
Enforce a timeout for Content Providers to be published.
ActivityManagerService: In the case where we are launching an application on behalf of a Content Provider request, enforce a timeout inbetween the application attaching and the content providers being published. Consider that a defective content provider may block in ContentProvider::onCreate indefinitely: in such a case the PROC_START_TIMEOUT has already been removed as the activity manager must have called bindApplication. In these cases, there will be nothing to wake threads blocking on the (non timed) wait for provider to be published at the end of ActivityManagerService::getContentProviderImpl. This can cause binder threads to block 1 by 1 until eventually AMS runs out and becomes unresponsive. Bug: 22141958 Change-Id: I2226da5df5c79b37f0b896423b3c1eaa4a7ecbba (cherry picked from commit da33c13434cb20a11b522374411a5b819503e4e0)
Diffstat (limited to 'services/core/java/com/android/server/am/ActivityManagerService.java')
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java50
1 files changed, 43 insertions, 7 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 525aac7..e3b5651 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -316,6 +316,9 @@ public final class ActivityManagerService extends ActivityManagerNative
// How long we wait for a launched process to attach to the activity manager
// before we decide it's never going to come up for real.
static final int PROC_START_TIMEOUT = 10*1000;
+ // How long we wait for an attached process to publish its content providers
+ // before we decide it must be hung.
+ static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
// How long we wait for a launched process to attach to the activity manager
// before we decide it's never going to come up for real, when the process was
@@ -1368,6 +1371,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
static final int APP_BOOST_DEACTIVATE_MSG = 58;
+ static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1701,6 +1705,12 @@ public final class ActivityManagerService extends ActivityManagerNative
processStartTimedOutLocked(app);
}
} break;
+ case CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG: {
+ ProcessRecord app = (ProcessRecord)msg.obj;
+ synchronized (ActivityManagerService.this) {
+ processContentProviderPublishTimedOutLocked(app);
+ }
+ } break;
case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
synchronized (ActivityManagerService.this) {
mStackSupervisor.doPendingActivityLaunchesLocked(true);
@@ -5944,6 +5954,11 @@ public final class ActivityManagerService extends ActivityManagerNative
return needRestart;
}
+ private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
+ cleanupAppInLaunchingProvidersLocked(app, true);
+ removeProcessLocked(app, false, true, "timeout publishing content providers");
+ }
+
private final void processStartTimedOutLocked(ProcessRecord app) {
final int pid = app.pid;
boolean gone = false;
@@ -5970,7 +5985,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
}
// Take care of any launching providers waiting for this process.
- checkAppInLaunchingProvidersLocked(app, true);
+ cleanupAppInLaunchingProvidersLocked(app, true);
// Take care of any services that are waiting for the process.
mServices.processStartTimedOutLocked(app);
app.kill("start timeout", true);
@@ -6066,6 +6081,12 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
+ if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
+ Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
+ msg.obj = app;
+ mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
+ }
+
if (!normalMode) {
Slog.i(TAG, "Launching preboot mode app: " + app);
}
@@ -9897,7 +9918,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final long origId = Binder.clearCallingIdentity();
final int N = providers.size();
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
ContentProviderHolder src = providers.get(i);
if (src == null || src.info == null || src.provider == null) {
continue;
@@ -9912,15 +9933,20 @@ public final class ActivityManagerService extends ActivityManagerNative
mProviderMap.putProviderByName(names[j], dst);
}
- int NL = mLaunchingProviders.size();
+ int launchingCount = mLaunchingProviders.size();
int j;
- for (j=0; j<NL; j++) {
+ boolean wasInLaunchingProviders = false;
+ for (j = 0; j < launchingCount; j++) {
if (mLaunchingProviders.get(j) == dst) {
mLaunchingProviders.remove(j);
+ wasInLaunchingProviders = true;
j--;
- NL--;
+ launchingCount--;
}
}
+ if (wasInLaunchingProviders) {
+ mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
+ }
synchronized (dst) {
dst.provider = src.provider;
dst.proc = r;
@@ -15531,7 +15557,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.pubProviders.clear();
// Take care of any launching providers waiting for this process.
- if (checkAppInLaunchingProvidersLocked(app, false)) {
+ if (cleanupAppInLaunchingProvidersLocked(app, false)) {
restart = true;
}
@@ -15653,7 +15679,17 @@ public final class ActivityManagerService extends ActivityManagerNative
return false;
}
- boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
+ boolean checkAppInLaunchingProvidersLocked(ProcessRecord app) {
+ for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
+ ContentProviderRecord cpr = mLaunchingProviders.get(i);
+ if (cpr.launchingApp == app) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean cleanupAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
// Look through the content providers we are waiting to have launched,
// and if any run in this process then either schedule a restart of
// the process or kill the client waiting for it if this process has