summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java61
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java3
2 files changed, 52 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 88d0e4b7344f..5b7a8148d694 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -568,6 +568,11 @@ public class ActivityManagerService extends IActivityManager.Stub
private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
+ /**
+ * How long between a process kill and we actually receive its death recipient
+ */
+ private static final long PROC_KILL_TIMEOUT = 5000; // 5 seconds;
+
OomAdjuster mOomAdjuster;
final LowMemDetector mLowMemDetector;
@@ -3738,6 +3743,9 @@ public class ActivityManagerService extends IActivityManager.Stub
"Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
handleAppDiedLocked(app, false, true);
+ // Execute the callback if there is any.
+ doAppDiedCallbackLocked(app);
+
if (doOomAdj) {
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
}
@@ -3749,6 +3757,10 @@ public class ActivityManagerService extends IActivityManager.Stub
reportUidInfoMessageLocked(TAG,
"Process " + app.processName + " (pid " + pid
+ ") has died and restarted (pid " + app.pid + ").", app.info.uid);
+
+ // Execute the callback if there is any.
+ doAppDiedCallbackLocked(app);
+
EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
} else if (DEBUG_PROCESSES) {
Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
@@ -3762,6 +3774,39 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ @GuardedBy("this")
+ private void doAppDiedCallbackLocked(final ProcessRecord app) {
+ if (app.mAppDiedCallback != null) {
+ app.mAppDiedCallback.run();
+ app.mAppDiedCallback = null;
+ }
+ }
+
+ @GuardedBy("this")
+ private void waitForProcKillLocked(final ProcessRecord app, final String formatString,
+ final long startTime) {
+ app.mAppDiedCallback = () -> {
+ synchronized (ActivityManagerService.this) {
+ // called when this app receives appDiedLocked()
+ ActivityManagerService.this.notifyAll();
+ }
+ };
+ checkTime(startTime, String.format(formatString, "before appDied"));
+ long now = SystemClock.uptimeMillis();
+ long timeout = PROC_KILL_TIMEOUT + now;
+ while (app.mAppDiedCallback != null && timeout > now) {
+ try {
+ wait(timeout - now);
+ } catch (InterruptedException e) {
+ }
+ now = SystemClock.uptimeMillis();
+ }
+ checkTime(startTime, String.format(formatString, "after appDied"));
+ if (app.mAppDiedCallback != null) {
+ Slog.w(TAG, String.format(formatString, "waiting for app killing timed out"));
+ }
+ }
+
/**
* If a stack trace dump file is configured, dump process stack traces.
* @param firstPids of dalvik VM processes to dump stack traces for first
@@ -6779,18 +6824,12 @@ public class ActivityManagerService extends IActivityManager.Stub
// Note if killedByAm is also set, this means the provider process has just been
// killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called
- // yet. So we need to call appDiedLocked() here and let it clean up.
+ // yet. So we need to wait for appDiedLocked() here and let it clean up.
// (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
// how to test this case.)
if (cpr.proc.killed && cpr.proc.killedByAm) {
- checkTime(startTime, "getContentProviderImpl: before appDied (killedByAm)");
- final long iden = Binder.clearCallingIdentity();
- try {
- appDiedLocked(cpr.proc);
- } finally {
- Binder.restoreCallingIdentity(iden);
- }
- checkTime(startTime, "getContentProviderImpl: after appDied (killedByAm)");
+ waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s (killedByAm)",
+ startTime);
}
}
@@ -6894,9 +6933,7 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
+ " is crashing; detaching " + r);
boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- checkTime(startTime, "getContentProviderImpl: before appDied");
- appDiedLocked(cpr.proc);
- checkTime(startTime, "getContentProviderImpl: after appDied");
+ waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s", startTime);
if (!lastRef) {
// This wasn't the last ref our process had on
// the provider... we have now been killed, bail.
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 5db6ff79b00f..867571a33bc2 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -329,6 +329,9 @@ class ProcessRecord implements WindowProcessListener {
boolean mReachable; // Whether or not this process is reachable from given process
+ // A callback that should be executed on app died; after that it'll be set to null
+ Runnable mAppDiedCallback;
+
void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
long startTime) {
this.startUid = startUid;