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

Commit b1c16343 authored by Jeffrey Huang's avatar Jeffrey Huang
Browse files

Migrate ProcessMemory pullers

Test: atest UidAtomTests#testProcessMemoryState
Test: atest UidAtomTests#testProcessMemoryHighWaterMark
Test: atest UidAtomTests#testProcessMemorySnapshot
Test: adb shell cmd stats pull-source 10013
Test: adb shell cmd stats pull-source 10042
Test: adb shell cmd stats pull-source 10064
Change-Id: I0ce870a3fec668e380a6b6412f278033d6734f35
parent 250e7aad
Loading
Loading
Loading
Loading
+0 −141
Original line number Diff line number Diff line
@@ -722,132 +722,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
        pulledData.add(e);
    }

    private void pullProcessMemoryState(
            int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
        List<ProcessMemoryState> processMemoryStates =
                LocalServices.getService(
                        ActivityManagerInternal.class).getMemoryStateForProcesses();
        for (ProcessMemoryState processMemoryState : processMemoryStates) {
            final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid,
                    processMemoryState.pid);
            if (memoryStat == null) {
                continue;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(processMemoryState.uid);
            e.writeString(processMemoryState.processName);
            e.writeInt(processMemoryState.oomScore);
            e.writeLong(memoryStat.pgfault);
            e.writeLong(memoryStat.pgmajfault);
            e.writeLong(memoryStat.rssInBytes);
            e.writeLong(memoryStat.cacheInBytes);
            e.writeLong(memoryStat.swapInBytes);
            e.writeLong(-1);  // unused
            e.writeLong(-1);  // unused
            e.writeInt(-1);  // unsed
            pulledData.add(e);
        }
    }

    private void pullProcessMemoryHighWaterMark(
            int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
        List<ProcessMemoryState> managedProcessList =
                LocalServices.getService(
                        ActivityManagerInternal.class).getMemoryStateForProcesses();
        for (ProcessMemoryState managedProcess : managedProcessList) {
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
            if (snapshot == null) {
                continue;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(managedProcess.uid);
            e.writeString(managedProcess.processName);
            // RSS high-water mark in bytes.
            e.writeLong((long) snapshot.rssHighWaterMarkInKilobytes * 1024L);
            e.writeInt(snapshot.rssHighWaterMarkInKilobytes);
            pulledData.add(e);
        }
        forEachPid((pid, cmdLine) -> {
            if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
                return;
            }
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
            if (snapshot == null) {
                return;
            }
            // Sometimes we get here a process that is not included in the whitelist. It comes
            // from forking the zygote for an app. We can ignore that sample because this process
            // is collected by ProcessMemoryState.
            if (isAppUid(snapshot.uid)) {
                return;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(snapshot.uid);
            e.writeString(cmdLine);
            // RSS high-water mark in bytes.
            e.writeLong((long) snapshot.rssHighWaterMarkInKilobytes * 1024L);
            e.writeInt(snapshot.rssHighWaterMarkInKilobytes);
            pulledData.add(e);
        });
        // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
        SystemProperties.set("sys.rss_hwm_reset.on", "1");
    }

    private void pullProcessMemorySnapshot(
            int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
        List<ProcessMemoryState> managedProcessList =
                LocalServices.getService(
                        ActivityManagerInternal.class).getMemoryStateForProcesses();
        for (ProcessMemoryState managedProcess : managedProcessList) {
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
            if (snapshot == null) {
                continue;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(managedProcess.uid);
            e.writeString(managedProcess.processName);
            e.writeInt(managedProcess.pid);
            e.writeInt(managedProcess.oomScore);
            e.writeInt(snapshot.rssInKilobytes);
            e.writeInt(snapshot.anonRssInKilobytes);
            e.writeInt(snapshot.swapInKilobytes);
            e.writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes);
            pulledData.add(e);
        }
        forEachPid((pid, cmdLine) -> {
            if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
                return;
            }
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
            if (snapshot == null) {
                return;
            }
            // Sometimes we get here a process that is not included in the whitelist. It comes
            // from forking the zygote for an app. We can ignore that sample because this process
            // is collected by ProcessMemoryState.
            if (isAppUid(snapshot.uid)) {
                return;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(snapshot.uid);
            e.writeString(cmdLine);
            e.writeInt(pid);
            e.writeInt(-1001);  // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.
            e.writeInt(snapshot.rssInKilobytes);
            e.writeInt(snapshot.anonRssInKilobytes);
            e.writeInt(snapshot.swapInKilobytes);
            e.writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes);
            pulledData.add(e);
        });
    }

    private static boolean isAppUid(int uid) {
        return uid >= MIN_APP_UID;
    }

    private void pullSystemIonHeapSize(
            int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
@@ -1823,21 +1697,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                break;
            }

            case StatsLog.PROCESS_MEMORY_STATE: {
                pullProcessMemoryState(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: {
                pullProcessMemoryHighWaterMark(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.PROCESS_MEMORY_SNAPSHOT: {
                pullProcessMemorySnapshot(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.SYSTEM_ION_HEAP_SIZE: {
                pullSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret);
                break;
+0 −14
Original line number Diff line number Diff line
@@ -95,20 +95,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
        {{.atomTag = android::util::BATTERY_CYCLE_COUNT},
         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},

        // process_memory_state
        {{.atomTag = android::util::PROCESS_MEMORY_STATE},
         {.additiveFields = {4, 5, 6, 7, 8},
          .puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},

        // process_memory_high_water_mark
        {{.atomTag = android::util::PROCESS_MEMORY_HIGH_WATER_MARK},
         {.puller =
                  new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},

        // process_memory_snapshot
        {{.atomTag = android::util::PROCESS_MEMORY_SNAPSHOT},
         {.puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_SNAPSHOT)}},

        // system_ion_heap_size
        {{.atomTag = android::util::SYSTEM_ION_HEAP_SIZE},
         {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}},
+189 −9
Original line number Diff line number Diff line
@@ -1004,27 +1004,207 @@ public class StatsPullAtomService extends SystemService {
    }

    private void registerProcessMemoryState() {
        // No op.
        int tagId = StatsLog.PROCESS_MEMORY_STATE;
        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
                .setAdditiveFields(new int[] {4, 5, 6, 7, 8})
                .build();
        mStatsManager.registerPullAtomCallback(
                tagId,
                metadata,
                (atomTag, data) -> pullProcessMemoryState(atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullProcessMemoryState() {
        // No op.
    private int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
        List<ProcessMemoryState> processMemoryStates =
                LocalServices.getService(ActivityManagerInternal.class)
                        .getMemoryStateForProcesses();
        for (ProcessMemoryState processMemoryState : processMemoryStates) {
            final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid,
                    processMemoryState.pid);
            if (memoryStat == null) {
                continue;
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeInt(processMemoryState.uid)
                    .writeString(processMemoryState.processName)
                    .writeInt(processMemoryState.oomScore)
                    .writeLong(memoryStat.pgfault)
                    .writeLong(memoryStat.pgmajfault)
                    .writeLong(memoryStat.rssInBytes)
                    .writeLong(memoryStat.cacheInBytes)
                    .writeLong(memoryStat.swapInBytes)
                    .writeLong(-1)  // unused
                    .writeLong(-1)  // unused
                    .writeInt(-1)  // unused
                    .build();
            pulledData.add(e);
        }
        return StatsManager.PULL_SUCCESS;
    }

    /**
     * Which native processes to snapshot memory for.
     *
     * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
     * /system/bin/statsd for the stats daemon.
     */
    private static final Set<String> MEMORY_INTERESTING_NATIVE_PROCESSES = Sets.newHashSet(
            "/system/bin/statsd",  // Stats daemon.
            "/system/bin/surfaceflinger",
            "/system/bin/apexd",  // APEX daemon.
            "/system/bin/audioserver",
            "/system/bin/cameraserver",
            "/system/bin/drmserver",
            "/system/bin/healthd",
            "/system/bin/incidentd",
            "/system/bin/installd",
            "/system/bin/lmkd",  // Low memory killer daemon.
            "/system/bin/logd",
            "media.codec",
            "media.extractor",
            "media.metrics",
            "/system/bin/mediadrmserver",
            "/system/bin/mediaserver",
            "/system/bin/performanced",
            "/system/bin/tombstoned",
            "/system/bin/traced",  // Perfetto.
            "/system/bin/traced_probes",  // Perfetto.
            "webview_zygote",
            "zygote",
            "zygote64");

    /**
     * Lowest available uid for apps.
     *
     * <p>Used to quickly discard memory snapshots of the zygote forks from native process
     * measurements.
     */
    private static final int MIN_APP_UID = 10_000;

    private static boolean isAppUid(int uid) {
        return uid >= MIN_APP_UID;
    }

    private void registerProcessMemoryHighWaterMark() {
        // No op.
        int tagId = StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullProcessMemoryHighWaterMark(atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullProcessMemoryHighWaterMark() {
        // No op.
    private int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
        List<ProcessMemoryState> managedProcessList =
                LocalServices.getService(ActivityManagerInternal.class)
                        .getMemoryStateForProcesses();
        for (ProcessMemoryState managedProcess : managedProcessList) {
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
            if (snapshot == null) {
                continue;
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeInt(managedProcess.uid)
                    .writeString(managedProcess.processName)
                    // RSS high-water mark in bytes.
                    .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
                    .writeInt(snapshot.rssHighWaterMarkInKilobytes)
                    .build();
            pulledData.add(e);
        }
        forEachPid((pid, cmdLine) -> {
            if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
                return;
            }
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
            if (snapshot == null) {
                return;
            }
            // Sometimes we get here a process that is not included in the whitelist. It comes
            // from forking the zygote for an app. We can ignore that sample because this process
            // is collected by ProcessMemoryState.
            if (isAppUid(snapshot.uid)) {
                return;
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeInt(snapshot.uid)
                    .writeString(cmdLine)
                    // RSS high-water mark in bytes.
                    .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
                    .writeInt(snapshot.rssHighWaterMarkInKilobytes)
                    .build();
            pulledData.add(e);
        });
        // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
        SystemProperties.set("sys.rss_hwm_reset.on", "1");
        return StatsManager.PULL_SUCCESS;
    }

    private void registerProcessMemorySnapshot() {
        // No op.
        int tagId = StatsLog.PROCESS_MEMORY_SNAPSHOT;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullProcessMemorySnapshot(atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullProcessMemorySnapshot() {
        // No op.
    private int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
        List<ProcessMemoryState> managedProcessList =
                LocalServices.getService(ActivityManagerInternal.class)
                        .getMemoryStateForProcesses();
        for (ProcessMemoryState managedProcess : managedProcessList) {
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
            if (snapshot == null) {
                continue;
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .writeInt(managedProcess.uid)
                    .writeString(managedProcess.processName)
                    .writeInt(managedProcess.pid)
                    .writeInt(managedProcess.oomScore)
                    .writeInt(snapshot.rssInKilobytes)
                    .writeInt(snapshot.anonRssInKilobytes)
                    .writeInt(snapshot.swapInKilobytes)
                    .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes)
                    .build();
            pulledData.add(e);
        }
        forEachPid((pid, cmdLine) -> {
            if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
                return;
            }
            final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
            if (snapshot == null) {
                return;
            }
            // Sometimes we get here a process that is not included in the whitelist. It comes
            // from forking the zygote for an app. We can ignore that sample because this process
            // is collected by ProcessMemoryState.
            if (isAppUid(snapshot.uid)) {
                return;
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeInt(snapshot.uid)
                    .writeString(cmdLine)
                    .writeInt(pid)
                    .writeInt(-1001)  // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.
                    .writeInt(snapshot.rssInKilobytes)
                    .writeInt(snapshot.anonRssInKilobytes)
                    .writeInt(snapshot.swapInKilobytes)
                    .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes)
                    .build();
            pulledData.add(e);
        });
        return StatsManager.PULL_SUCCESS;
    }

    private void registerSystemIonHeapSize() {