Work on issue 2259506: camera ANRed and then device runtime restarted
If a process fails to come up, we could leave content providers and
services hanging around.
Change-Id: Iff5b8ce3b933580954724338a89e110e45f1b00c
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index aa79ab4..3612a9b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -185,6 +185,7 @@
static final int LOG_AM_SERVICE_CRASHED_TOO_MUCH = 30034;
static final int LOG_AM_SCHEDULE_SERVICE_RESTART = 30035;
static final int LOG_AM_PROVIDER_LOST_PROCESS = 30036;
+ static final int LOG_AM_PROCESS_START_TIMEOUT = 30037;
static final int LOG_BOOT_PROGRESS_AMS_READY = 3040;
static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
@@ -5199,13 +5200,23 @@
if (gone) {
Log.w(TAG, "Process " + app + " failed to attach");
+ EventLog.writeEvent(LOG_AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
+ app.processName);
mProcessNames.remove(app.processName, app.info.uid);
- Process.killProcess(pid);
- if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
- Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
- mPendingBroadcast = null;
- scheduleBroadcastsLocked();
+ // Take care of any launching providers waiting for this process.
+ checkAppInLaunchingProvidersLocked(app, true);
+ // Take care of any services that are waiting for the process.
+ for (int i=0; i<mPendingServices.size(); i++) {
+ ServiceRecord sr = mPendingServices.get(i);
+ if (app.info.uid == sr.appInfo.uid
+ && app.processName.equals(sr.processName)) {
+ Log.w(TAG, "Forcing bringing down service: " + sr);
+ mPendingServices.remove(i);
+ i--;
+ bringDownServiceLocked(sr, true);
+ }
}
+ Process.killProcess(pid);
if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Log.w(TAG, "Unattached app died before backup, skipping");
try {
@@ -5216,6 +5227,11 @@
// Can't happen; the backup manager is local
}
}
+ if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
+ Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
+ mPendingBroadcast = null;
+ scheduleBroadcastsLocked();
+ }
} else {
Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
}
@@ -9949,23 +9965,11 @@
app.pubProviders.clear();
}
- // 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
- // gone bad.
- for (int i=0; i<NL; i++) {
- ContentProviderRecord cpr = (ContentProviderRecord)
- mLaunchingProviders.get(i);
- if (cpr.launchingApp == app) {
- if (!app.bad) {
- restart = true;
- } else {
- removeDyingProviderLocked(app, cpr);
- NL = mLaunchingProviders.size();
- }
- }
+ // Take care of any launching providers waiting for this process.
+ if (checkAppInLaunchingProvidersLocked(app, false)) {
+ restart = true;
}
-
+
// Unregister from connected content providers.
if (!app.conProviders.isEmpty()) {
Iterator it = app.conProviders.keySet().iterator();
@@ -10060,6 +10064,28 @@
}
}
+ boolean checkAppInLaunchingProvidersLocked(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
+ // gone bad.
+ int NL = mLaunchingProviders.size();
+ boolean restart = false;
+ for (int i=0; i<NL; i++) {
+ ContentProviderRecord cpr = (ContentProviderRecord)
+ mLaunchingProviders.get(i);
+ if (cpr.launchingApp == app) {
+ if (!alwaysBad && !app.bad) {
+ restart = true;
+ } else {
+ removeDyingProviderLocked(app, cpr);
+ NL = mLaunchingProviders.size();
+ }
+ }
+ }
+ return restart;
+ }
+
// =========================================================
// SERVICES
// =========================================================