Loading core/java/android/app/ActivityThread.java +11 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,7 @@ import com.android.internal.os.DebugStore; import com.android.internal.os.RuntimeInit; import com.android.internal.os.SafeZipPathValidatorCallback; import com.android.internal.os.SomeArgs; import com.android.internal.os.logging.MetricsLoggerWrapper; import com.android.internal.policy.DecorView; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; Loading Loading @@ -7675,6 +7676,16 @@ public final class ActivityThread extends ClientTransactionHandler } } }); // Register callback to report native memory metrics post GC cleanup if (Flags.reportPostgcMemoryMetrics() && com.android.libcore.readonly.Flags.postCleanupApis()) { VMRuntime.addPostCleanupCallback(new Runnable() { @Override public void run() { MetricsLoggerWrapper.logPostGcMemorySnapshot(); } }); } } @UnsupportedAppUsage Loading core/java/android/app/metrics.aconfig 0 → 100644 +10 −0 Original line number Diff line number Diff line package: "android.app" container: "system" flag { namespace: "system_performance" name: "report_postgc_memory_metrics" is_exported: false description: "Controls whether to report memory metrics post GC cleanup" bug: "331243037" } services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java→core/java/com/android/internal/os/ProcfsMemoryUtil.java +66 −8 Original line number Diff line number Diff line Loading @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.stats.pull; package com.android.internal.os; import static android.os.Process.PROC_OUT_STRING; import static android.os.Process.*; import android.annotation.Nullable; import android.os.Process; Loading @@ -23,6 +23,7 @@ import android.util.SparseArray; public final class ProcfsMemoryUtil { private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING }; private static final int[] OOM_SCORE_ADJ_OUT = new int[] { PROC_NEWLINE_TERM | PROC_OUT_LONG }; private static final String[] STATUS_KEYS = new String[] { "Uid:", "VmHWM:", Loading @@ -38,17 +39,34 @@ public final class ProcfsMemoryUtil { private ProcfsMemoryUtil() {} /** * Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS, * VmSwap, RssShmem fields in /proc/pid/status in kilobytes or null if not available. * Reads memory stats of a process from procfs. * * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in * /proc/pid/status in kilobytes or null if not available. */ @Nullable public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) { return readMemorySnapshotFromProcfs("/proc/" + pid + "/status"); } /** * Reads memory stats of the current process from procfs. * * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in * /proc/self/status in kilobytes or null if not available. */ @Nullable public static MemorySnapshot readMemorySnapshotFromProcfs() { return readMemorySnapshotFromProcfs("/proc/self/status"); } private static MemorySnapshot readMemorySnapshotFromProcfs(String path) { long[] output = new long[STATUS_KEYS.length]; output[0] = -1; output[3] = -1; output[4] = -1; output[5] = -1; Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output); Process.readProcLines(path, STATUS_KEYS, output); if (output[0] == -1 || output[3] == -1 || output[4] == -1 || output[5] == -1) { // Could not open or parse file. return null; Loading @@ -70,13 +88,53 @@ public final class ProcfsMemoryUtil { * if the file is not available. */ public static String readCmdlineFromProcfs(int pid) { return readCmdlineFromProcfs("/proc/" + pid + "/cmdline"); } /** * Reads cmdline of the current process from procfs. * * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string * if the file is not available. */ public static String readCmdlineFromProcfs() { return readCmdlineFromProcfs("/proc/self/cmdline"); } private static String readCmdlineFromProcfs(String path) { String[] cmdline = new String[1]; if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) { if (!Process.readProcFile(path, CMDLINE_OUT, cmdline, null, null)) { return ""; } return cmdline[0]; } /** * Reads oom_score_adj of a process from procfs * * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails. */ public static int readOomScoreAdjFromProcfs(int pid) { return readOomScoreAdjFromProcfs("/proc/" + pid + "/oom_score_adj"); } /** * Reads oom_score_adj of the current process from procfs * * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails. */ public static int readOomScoreAdjFromProcfs() { return readOomScoreAdjFromProcfs("/proc/self/oom_score_adj"); } private static int readOomScoreAdjFromProcfs(String path) { long[] oom_score_adj = new long[1]; if (Process.readProcFile(path, OOM_SCORE_ADJ_OUT, null, oom_score_adj, null)) { return (int)oom_score_adj[0]; } return 0; } /** * Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline. */ Loading Loading @@ -109,7 +167,7 @@ public final class ProcfsMemoryUtil { /** Reads and parses selected entries of /proc/vmstat. */ @Nullable static VmStat readVmStat() { public static VmStat readVmStat() { long[] vmstat = new long[VMSTAT_KEYS.length]; vmstat[0] = -1; Process.readProcLines("/proc/vmstat", VMSTAT_KEYS, vmstat); Loading @@ -121,7 +179,7 @@ public final class ProcfsMemoryUtil { return result; } static final class VmStat { public static final class VmStat { public int oomKillCount; } } core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java +48 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,15 @@ package com.android.internal.os.logging; import android.app.Application; import android.os.Process; import android.util.Log; import android.view.WindowManager.LayoutParams; import com.android.internal.os.ProcfsMemoryUtil; import com.android.internal.util.FrameworkStatsLog; import java.util.Collection; import libcore.util.NativeAllocationRegistry; /** * Used to wrap different logging calls in one, so that client side code base is clean and more Loading Loading @@ -49,4 +55,46 @@ public class MetricsLoggerWrapper { } } } public static void logPostGcMemorySnapshot() { if (!com.android.libcore.Flags.nativeMetrics()) { return; } int pid = Process.myPid(); String processName = Application.getProcessName(); Collection<NativeAllocationRegistry.Metrics> metrics = NativeAllocationRegistry.getMetrics(); int nMetrics = metrics.size(); String[] classNames = new String[nMetrics]; long[] mallocedCount = new long[nMetrics]; long[] mallocedBytes = new long[nMetrics]; long[] nonmallocedCount = new long[nMetrics]; long[] nonmallocedBytes = new long[nMetrics]; int i = 0; for (NativeAllocationRegistry.Metrics m : metrics) { classNames[i] = m.getClassName(); mallocedCount[i] = m.getMallocedCount(); mallocedBytes[i] = m.getMallocedBytes(); nonmallocedCount[i] = m.getNonmallocedCount(); nonmallocedBytes[i] = m.getNonmallocedBytes(); i++; } ProcfsMemoryUtil.MemorySnapshot m = ProcfsMemoryUtil.readMemorySnapshotFromProcfs(); int oom_score_adj = ProcfsMemoryUtil.readOomScoreAdjFromProcfs(); FrameworkStatsLog.write(FrameworkStatsLog.POSTGC_MEMORY_SNAPSHOT, m.uid, processName, pid, oom_score_adj, m.rssInKilobytes, m.anonRssInKilobytes, m.swapInKilobytes, m.anonRssInKilobytes + m.swapInKilobytes, classNames, mallocedCount, mallocedBytes, nonmallocedCount, nonmallocedBytes); } } services/core/java/com/android/server/am/ProcessErrorStateRecord.java +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ 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 static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; import android.annotation.Nullable; import android.app.ActivityManager; Loading Loading @@ -58,7 +58,7 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.modules.expresslog.Counter; import com.android.server.ResourcePressureUtil; import com.android.server.criticalevents.CriticalEventLog; import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot; import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot; import com.android.server.wm.WindowProcessController; import java.io.File; Loading Loading
core/java/android/app/ActivityThread.java +11 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,7 @@ import com.android.internal.os.DebugStore; import com.android.internal.os.RuntimeInit; import com.android.internal.os.SafeZipPathValidatorCallback; import com.android.internal.os.SomeArgs; import com.android.internal.os.logging.MetricsLoggerWrapper; import com.android.internal.policy.DecorView; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; Loading Loading @@ -7675,6 +7676,16 @@ public final class ActivityThread extends ClientTransactionHandler } } }); // Register callback to report native memory metrics post GC cleanup if (Flags.reportPostgcMemoryMetrics() && com.android.libcore.readonly.Flags.postCleanupApis()) { VMRuntime.addPostCleanupCallback(new Runnable() { @Override public void run() { MetricsLoggerWrapper.logPostGcMemorySnapshot(); } }); } } @UnsupportedAppUsage Loading
core/java/android/app/metrics.aconfig 0 → 100644 +10 −0 Original line number Diff line number Diff line package: "android.app" container: "system" flag { namespace: "system_performance" name: "report_postgc_memory_metrics" is_exported: false description: "Controls whether to report memory metrics post GC cleanup" bug: "331243037" }
services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java→core/java/com/android/internal/os/ProcfsMemoryUtil.java +66 −8 Original line number Diff line number Diff line Loading @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.stats.pull; package com.android.internal.os; import static android.os.Process.PROC_OUT_STRING; import static android.os.Process.*; import android.annotation.Nullable; import android.os.Process; Loading @@ -23,6 +23,7 @@ import android.util.SparseArray; public final class ProcfsMemoryUtil { private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING }; private static final int[] OOM_SCORE_ADJ_OUT = new int[] { PROC_NEWLINE_TERM | PROC_OUT_LONG }; private static final String[] STATUS_KEYS = new String[] { "Uid:", "VmHWM:", Loading @@ -38,17 +39,34 @@ public final class ProcfsMemoryUtil { private ProcfsMemoryUtil() {} /** * Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS, * VmSwap, RssShmem fields in /proc/pid/status in kilobytes or null if not available. * Reads memory stats of a process from procfs. * * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in * /proc/pid/status in kilobytes or null if not available. */ @Nullable public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) { return readMemorySnapshotFromProcfs("/proc/" + pid + "/status"); } /** * Reads memory stats of the current process from procfs. * * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in * /proc/self/status in kilobytes or null if not available. */ @Nullable public static MemorySnapshot readMemorySnapshotFromProcfs() { return readMemorySnapshotFromProcfs("/proc/self/status"); } private static MemorySnapshot readMemorySnapshotFromProcfs(String path) { long[] output = new long[STATUS_KEYS.length]; output[0] = -1; output[3] = -1; output[4] = -1; output[5] = -1; Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output); Process.readProcLines(path, STATUS_KEYS, output); if (output[0] == -1 || output[3] == -1 || output[4] == -1 || output[5] == -1) { // Could not open or parse file. return null; Loading @@ -70,13 +88,53 @@ public final class ProcfsMemoryUtil { * if the file is not available. */ public static String readCmdlineFromProcfs(int pid) { return readCmdlineFromProcfs("/proc/" + pid + "/cmdline"); } /** * Reads cmdline of the current process from procfs. * * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string * if the file is not available. */ public static String readCmdlineFromProcfs() { return readCmdlineFromProcfs("/proc/self/cmdline"); } private static String readCmdlineFromProcfs(String path) { String[] cmdline = new String[1]; if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) { if (!Process.readProcFile(path, CMDLINE_OUT, cmdline, null, null)) { return ""; } return cmdline[0]; } /** * Reads oom_score_adj of a process from procfs * * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails. */ public static int readOomScoreAdjFromProcfs(int pid) { return readOomScoreAdjFromProcfs("/proc/" + pid + "/oom_score_adj"); } /** * Reads oom_score_adj of the current process from procfs * * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails. */ public static int readOomScoreAdjFromProcfs() { return readOomScoreAdjFromProcfs("/proc/self/oom_score_adj"); } private static int readOomScoreAdjFromProcfs(String path) { long[] oom_score_adj = new long[1]; if (Process.readProcFile(path, OOM_SCORE_ADJ_OUT, null, oom_score_adj, null)) { return (int)oom_score_adj[0]; } return 0; } /** * Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline. */ Loading Loading @@ -109,7 +167,7 @@ public final class ProcfsMemoryUtil { /** Reads and parses selected entries of /proc/vmstat. */ @Nullable static VmStat readVmStat() { public static VmStat readVmStat() { long[] vmstat = new long[VMSTAT_KEYS.length]; vmstat[0] = -1; Process.readProcLines("/proc/vmstat", VMSTAT_KEYS, vmstat); Loading @@ -121,7 +179,7 @@ public final class ProcfsMemoryUtil { return result; } static final class VmStat { public static final class VmStat { public int oomKillCount; } }
core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java +48 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,15 @@ package com.android.internal.os.logging; import android.app.Application; import android.os.Process; import android.util.Log; import android.view.WindowManager.LayoutParams; import com.android.internal.os.ProcfsMemoryUtil; import com.android.internal.util.FrameworkStatsLog; import java.util.Collection; import libcore.util.NativeAllocationRegistry; /** * Used to wrap different logging calls in one, so that client side code base is clean and more Loading Loading @@ -49,4 +55,46 @@ public class MetricsLoggerWrapper { } } } public static void logPostGcMemorySnapshot() { if (!com.android.libcore.Flags.nativeMetrics()) { return; } int pid = Process.myPid(); String processName = Application.getProcessName(); Collection<NativeAllocationRegistry.Metrics> metrics = NativeAllocationRegistry.getMetrics(); int nMetrics = metrics.size(); String[] classNames = new String[nMetrics]; long[] mallocedCount = new long[nMetrics]; long[] mallocedBytes = new long[nMetrics]; long[] nonmallocedCount = new long[nMetrics]; long[] nonmallocedBytes = new long[nMetrics]; int i = 0; for (NativeAllocationRegistry.Metrics m : metrics) { classNames[i] = m.getClassName(); mallocedCount[i] = m.getMallocedCount(); mallocedBytes[i] = m.getMallocedBytes(); nonmallocedCount[i] = m.getNonmallocedCount(); nonmallocedBytes[i] = m.getNonmallocedBytes(); i++; } ProcfsMemoryUtil.MemorySnapshot m = ProcfsMemoryUtil.readMemorySnapshotFromProcfs(); int oom_score_adj = ProcfsMemoryUtil.readOomScoreAdjFromProcfs(); FrameworkStatsLog.write(FrameworkStatsLog.POSTGC_MEMORY_SNAPSHOT, m.uid, processName, pid, oom_score_adj, m.rssInKilobytes, m.anonRssInKilobytes, m.swapInKilobytes, m.anonRssInKilobytes + m.swapInKilobytes, classNames, mallocedCount, mallocedBytes, nonmallocedCount, nonmallocedBytes); } }
services/core/java/com/android/server/am/ProcessErrorStateRecord.java +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ 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 static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; import android.annotation.Nullable; import android.app.ActivityManager; Loading Loading @@ -58,7 +58,7 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.modules.expresslog.Counter; import com.android.server.ResourcePressureUtil; import com.android.server.criticalevents.CriticalEventLog; import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot; import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot; import com.android.server.wm.WindowProcessController; import java.io.File; Loading