Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7060f86 authored by Alessio Balsini's avatar Alessio Balsini
Browse files

Parser for DMA buffer memory allocations in procfs



Extend the parsing of per-process memory allocations with allocations
related to DMA-buffer RSS.
This is done both for the current RSS and for the high water mark
pullers.

Bug: 424648392
Test: statsd_testdrive 10064
Flag: EXEMPT Atom puller change
Change-Id: I4ac944128d3d104c5377d04ac6c3047933f89011
Signed-off-by: default avatarAlessio Balsini <balsini@google.com>
parent 34cab6d6
Loading
Loading
Loading
Loading
+51 −1
Original line number Diff line number Diff line
@@ -15,7 +15,9 @@
 */
package com.android.internal.os;

import static android.os.Process.*;
import static android.os.Process.PROC_NEWLINE_TERM;
import static android.os.Process.PROC_OUT_LONG;
import static android.os.Process.PROC_OUT_STRING;

import android.annotation.Nullable;
import android.os.Process;
@@ -35,6 +37,13 @@ public final class ProcfsMemoryUtil {
    private static final String[] VMSTAT_KEYS = new String[] {
            "oom_kill"
    };
    private static final int[] DMABUF_FILE_FORMAT = new int[] {PROC_OUT_LONG};

    public enum DmaBufType {
        RSS,
        RSS_HWM,
        PSS
    };

    private ProcfsMemoryUtil() {}

@@ -81,6 +90,47 @@ public final class ProcfsMemoryUtil {
        return snapshot;
    }

    /**
     * Reads dmabuf stats of the current process from procfs.
     *
     * <p>Returns values related to RSS, RSS_HWM and PSS from, respectively, /proc/pid/{dmabuf_rss,
     * dmabuf_rss_hwm, dmabuf_pss}, in kilobytes or -1 if not available.
     */
    public static int readDmabufFromProcfs(DmaBufType type, int pid) {
        return readDmabufFromProcfs(type, String.valueOf(pid));
    }

    /**
     * Reads dmabuf stats of the current process from procfs.
     *
     * <p>Returns values related to RSS, RSS_HWM and PSS from, respectively, /proc/self/{dmabuf_rss,
     * dmabuf_rss_hwm, dmabuf_pss}, in kilobytes or -1 if not available.
     */
    public static int readDmabufFromProcfs(DmaBufType type) {
        return readDmabufFromProcfs(type, "self");
    }

    private static int readDmabufFromProcfs(DmaBufType type, String path) {
        // These files have maximum 1 line.
        long[] output = new long[1];
        String dmabuf_file = switch (type) {
            case RSS -> "dmabuf_rss";
            case RSS_HWM -> "dmabuf_rss_hwm";
            case PSS -> "dmabuf_pss";
        };

        if (!Process.readProcFile(
                "/proc/" + path + "/" + dmabuf_file, DMABUF_FILE_FORMAT, null, output, null)) {
            /* Catches the case when the file is empty, doesn't exist, or the
             * kernel does not support reporting these values. We should not
             * report the value 0, as it would correspond to no dmabuf memory
             * allocations, so we report an error value of -1. */
            return -1;
        }

        return (int) (output[0] / 1024);
    }

    /**
     * Reads cmdline of a process from procfs.
     *
+62 −27
Original line number Diff line number Diff line
@@ -49,8 +49,10 @@ import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.util.MathUtils.constrain;
import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID;

import static com.android.internal.os.ProcfsMemoryUtil.DmaBufType;
import static com.android.internal.os.ProcfsMemoryUtil.getProcessCmdlines;
import static com.android.internal.os.ProcfsMemoryUtil.readCmdlineFromProcfs;
import static com.android.internal.os.ProcfsMemoryUtil.readDmabufFromProcfs;
import static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__GESTURE_SHORTCUT_TYPE__TRIPLE_TAP;
@@ -2486,11 +2488,17 @@ public class StatsPullAtomService extends SystemService {
            if (snapshot == null) {
                continue;
            }
            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, managedProcess.uid,
            final int dmaBufRssHighWaterMarkInKilobytes =
                    readDmabufFromProcfs(DmaBufType.RSS_HWM, managedProcess.pid);
            pulledData.add(
                    FrameworkStatsLog.buildStatsEvent(
                            atomTag,
                            managedProcess.uid,
                            managedProcess.processName,
                            // RSS high-water mark in bytes.
                            snapshot.rssHighWaterMarkInKilobytes * 1024L,
                    snapshot.rssHighWaterMarkInKilobytes));
                            snapshot.rssHighWaterMarkInKilobytes,
                            dmaBufRssHighWaterMarkInKilobytes));
        }
        // Complement the data with native system processes
        SparseArray<String> processCmdlines = getProcessCmdlines();
@@ -2501,11 +2509,17 @@ public class StatsPullAtomService extends SystemService {
            if (snapshot == null) {
                continue;
            }
            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, snapshot.uid,
            final int dmaBufRssHighWaterMarkInKilobytes =
                    readDmabufFromProcfs(DmaBufType.RSS_HWM, processCmdlines.keyAt(i));
            pulledData.add(
                    FrameworkStatsLog.buildStatsEvent(
                            atomTag,
                            snapshot.uid,
                            processCmdlines.valueAt(i),
                            // RSS high-water mark in bytes.
                            snapshot.rssHighWaterMarkInKilobytes * 1024L,
                    snapshot.rssHighWaterMarkInKilobytes));
                            snapshot.rssHighWaterMarkInKilobytes,
                            dmaBufRssHighWaterMarkInKilobytes));
        }
        // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
        SystemProperties.set("sys.rss_hwm_reset.on", "1");
@@ -2537,13 +2551,25 @@ public class StatsPullAtomService extends SystemService {
            if (snapshot == null) {
                continue;
            }
            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, managedProcess.uid,
                    managedProcess.processName, managedProcess.pid, managedProcess.oomScore,
                    snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
            final int dmaBufRssInKilobytes =
                    readDmabufFromProcfs(DmaBufType.RSS, managedProcess.pid);
            pulledData.add(
                    FrameworkStatsLog.buildStatsEvent(
                            atomTag,
                            managedProcess.uid,
                            managedProcess.processName,
                            managedProcess.pid,
                            managedProcess.oomScore,
                            snapshot.rssInKilobytes,
                            snapshot.anonRssInKilobytes,
                            snapshot.swapInKilobytes,
                            snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
                    gpuMemPerPid.get(managedProcess.pid), managedProcess.hasForegroundServices,
                    snapshot.rssShmemKilobytes, managedProcess.mHostingComponentTypes,
                    managedProcess.mHistoricalHostingComponentTypes));
                            gpuMemPerPid.get(managedProcess.pid),
                            managedProcess.hasForegroundServices,
                            snapshot.rssShmemKilobytes,
                            managedProcess.mHostingComponentTypes,
                            managedProcess.mHistoricalHostingComponentTypes,
                            dmaBufRssInKilobytes));
        }
        // Complement the data with native system processes. Given these measurements can be taken
        // in response to LMKs happening, we want to first collect the managed app stats (to
@@ -2557,16 +2583,25 @@ public class StatsPullAtomService extends SystemService {
            if (snapshot == null) {
                continue;
            }
            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, snapshot.uid,
                    processCmdlines.valueAt(i), pid,
            final int dmaBufRssInKilobytes = readDmabufFromProcfs(DmaBufType.RSS, pid);
            pulledData.add(
                    FrameworkStatsLog.buildStatsEvent(
                            atomTag,
                            snapshot.uid,
                            processCmdlines.valueAt(i),
                            pid,
                            -1001 /*Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.*/,
                    snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
                            snapshot.rssInKilobytes,
                            snapshot.anonRssInKilobytes,
                            snapshot.swapInKilobytes,
                            snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
                    gpuMemPerPid.get(pid), false /* has_foreground_services */,
                            gpuMemPerPid.get(pid),
                            false /* has_foreground_services */,
                            snapshot.rssShmemKilobytes,
                            // Native processes don't really have a hosting component type.
                            HOSTING_COMPONENT_TYPE_EMPTY,
                    HOSTING_COMPONENT_TYPE_EMPTY));
                            HOSTING_COMPONENT_TYPE_EMPTY,
                            dmaBufRssInKilobytes));
        }
        return StatsManager.PULL_SUCCESS;
    }