[ActivityManager] Examine bad process before clean up application
record Symptom: Unable to launch activity Root cause: There are some cases that would start process while pid assigned or already running. So the previous application record will be clean up via handleAppDiedLocked(), but it won't be removed from ActivityManager.mProcessNames since the process is supposed to be restart later. However, if the process is started from a background operation and has named as a bad process, it silently fail the launch. Then, the process won't ever be request to start afterward. The process status is app.pid > 0 and app.thread is null. The application components are unable to launch since then. Solution: Examine bad process before clean up application record Change-Id: I53dc06e49254094abc06e460c8b8b33f36803601
This commit is contained in:
@@ -2787,10 +2787,38 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (!isolated) {
|
||||
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
|
||||
checkTime(startTime, "startProcess: after getProcessRecord");
|
||||
|
||||
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
|
||||
// If we are in the background, then check to see if this process
|
||||
// is bad. If so, we will just silently fail.
|
||||
if (mBadProcesses.get(info.processName, info.uid) != null) {
|
||||
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
|
||||
+ "/" + info.processName);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// When the user is explicitly starting a process, then clear its
|
||||
// crash count so that we won't make it bad until they see at
|
||||
// least one crash dialog again, and make the process good again
|
||||
// if it had been bad.
|
||||
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
|
||||
+ "/" + info.processName);
|
||||
mProcessCrashTimes.remove(info.processName, info.uid);
|
||||
if (mBadProcesses.get(info.processName, info.uid) != null) {
|
||||
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
|
||||
UserHandle.getUserId(info.uid), info.uid,
|
||||
info.processName);
|
||||
mBadProcesses.remove(info.processName, info.uid);
|
||||
if (app != null) {
|
||||
app.bad = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If this is an isolated process, it can't re-use an existing process.
|
||||
app = null;
|
||||
}
|
||||
|
||||
// We don't have to do anything more if:
|
||||
// (1) There is an existing application record; and
|
||||
// (2) The caller doesn't think it is dead, OR there is no thread
|
||||
@@ -2824,35 +2852,6 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
String hostingNameStr = hostingName != null
|
||||
? hostingName.flattenToShortString() : null;
|
||||
|
||||
if (!isolated) {
|
||||
if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
|
||||
// If we are in the background, then check to see if this process
|
||||
// is bad. If so, we will just silently fail.
|
||||
if (mBadProcesses.get(info.processName, info.uid) != null) {
|
||||
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
|
||||
+ "/" + info.processName);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// When the user is explicitly starting a process, then clear its
|
||||
// crash count so that we won't make it bad until they see at
|
||||
// least one crash dialog again, and make the process good again
|
||||
// if it had been bad.
|
||||
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
|
||||
+ "/" + info.processName);
|
||||
mProcessCrashTimes.remove(info.processName, info.uid);
|
||||
if (mBadProcesses.get(info.processName, info.uid) != null) {
|
||||
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
|
||||
UserHandle.getUserId(info.uid), info.uid,
|
||||
info.processName);
|
||||
mBadProcesses.remove(info.processName, info.uid);
|
||||
if (app != null) {
|
||||
app.bad = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (app == null) {
|
||||
checkTime(startTime, "startProcess: creating new process record");
|
||||
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
|
||||
|
||||
Reference in New Issue
Block a user