diff options
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 61 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessRecord.java | 3 |
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; |