diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java index 1d48cb25f03ad..e66894b596e93 100644 --- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java @@ -22,7 +22,9 @@ import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR; import static com.android.server.am.ActivityManagerService.MY_PID; import static com.android.server.am.ProcessRecord.TAG; +import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AnrController; import android.app.ApplicationErrorReport; @@ -56,6 +58,7 @@ import com.android.internal.os.anr.AnrLatencyTracker; import com.android.internal.util.FrameworkStatsLog; import com.android.server.ResourcePressureUtil; import com.android.server.criticalevents.CriticalEventLog; +import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot; import com.android.server.wm.WindowProcessController; import java.io.File; @@ -396,6 +399,8 @@ class ProcessErrorStateRecord { }); } } + // Build memory headers for the ANRing process. + String memoryHeaders = buildMemoryHeadersFor(pid); // Get critical event log before logging the ANR so that it doesn't occur in the log. latencyTracker.criticalEventLogStarted(); @@ -496,7 +501,7 @@ class ProcessErrorStateRecord { File tracesFile = StackTracesDumpHelper.dumpStackTraces(firstPids, isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids, nativePidsFuture, tracesFileException, firstPidEndOffset, annotation, - criticalEventLog, auxiliaryTaskExecutor, latencyTracker); + criticalEventLog, memoryHeaders, auxiliaryTaskExecutor, latencyTracker); if (isMonitorCpuUsage()) { // Wait for the first call to finish @@ -710,6 +715,26 @@ class ProcessErrorStateRecord { resolver.getUserId()) != 0; } + private @Nullable String buildMemoryHeadersFor(int pid) { + if (pid <= 0) { + Slog.i(TAG, "Memory header requested with invalid pid: " + pid); + return null; + } + MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid); + if (snapshot == null) { + Slog.i(TAG, "Failed to get memory snapshot for pid:" + pid); + return null; + } + + StringBuilder memoryHeaders = new StringBuilder(); + memoryHeaders.append("RssHwmKb: ") + .append(snapshot.rssHighWaterMarkInKilobytes) + .append("\n"); + memoryHeaders.append("RssKb: ").append(snapshot.rssInKilobytes).append("\n"); + memoryHeaders.append("RssAnonKb: ").append(snapshot.anonRssInKilobytes).append("\n"); + memoryHeaders.append("VmSwapKb: ").append(snapshot.swapInKilobytes).append("\n"); + return memoryHeaders.toString(); + } /** * Unless configured otherwise, swallow ANRs in background processes & kill the process. * Non-private access is for tests only. diff --git a/services/core/java/com/android/server/am/StackTracesDumpHelper.java b/services/core/java/com/android/server/am/StackTracesDumpHelper.java index 937332894dbde..10ddc2f562dcf 100644 --- a/services/core/java/com/android/server/am/StackTracesDumpHelper.java +++ b/services/core/java/com/android/server/am/StackTracesDumpHelper.java @@ -85,7 +85,8 @@ public class StackTracesDumpHelper { Future> nativePidsFuture, StringWriter logExceptionCreatingFile, @NonNull Executor auxiliaryTaskExecutor, AnrLatencyTracker latencyTracker) { return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture, - logExceptionCreatingFile, null, null, null, auxiliaryTaskExecutor, latencyTracker); + logExceptionCreatingFile, null, null, null, null, auxiliaryTaskExecutor, + latencyTracker); } /** @@ -99,7 +100,7 @@ public class StackTracesDumpHelper { AnrLatencyTracker latencyTracker) { return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture, logExceptionCreatingFile, null, subject, criticalEventSection, - auxiliaryTaskExecutor, latencyTracker); + /* memoryHeaders= */ null, auxiliaryTaskExecutor, latencyTracker); } /** @@ -110,7 +111,8 @@ public class StackTracesDumpHelper { ProcessCpuTracker processCpuTracker, SparseBooleanArray lastPids, Future> nativePidsFuture, StringWriter logExceptionCreatingFile, AtomicLong firstPidEndOffset, String subject, String criticalEventSection, - @NonNull Executor auxiliaryTaskExecutor, AnrLatencyTracker latencyTracker) { + String memoryHeaders, @NonNull Executor auxiliaryTaskExecutor, + AnrLatencyTracker latencyTracker) { try { if (latencyTracker != null) { @@ -150,9 +152,10 @@ public class StackTracesDumpHelper { return null; } - if (subject != null || criticalEventSection != null) { + if (subject != null || criticalEventSection != null || memoryHeaders != null) { appendtoANRFile(tracesFile.getAbsolutePath(), - (subject != null ? "Subject: " + subject + "\n\n" : "") + (subject != null ? "Subject: " + subject + "\n" : "") + + (memoryHeaders != null ? memoryHeaders + "\n\n" : "") + (criticalEventSection != null ? criticalEventSection : "")); }