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

Commit 598e9a27 authored by Kweku Adams's avatar Kweku Adams
Browse files

incidentd: dumping native process mem info to proto.

Bug: 65750823
Test: flash device and check proto dump output.
Change-Id: Ic584f78153fbbb507cdd41e699a541e3351467bb
parent b4f84afc
Loading
Loading
Loading
Loading
+163 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.SuperNotCalledException;
import android.util.proto.ProtoOutputStream;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.ThreadedRenderer;
@@ -131,6 +132,7 @@ import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.org.conscrypt.OpenSSLSocketImpl;
import com.android.org.conscrypt.TrustedCertificateStore;
import com.android.server.am.proto.MemInfoProto;

import dalvik.system.BaseDexClassLoader;
import dalvik.system.CloseGuard;
@@ -2259,6 +2261,167 @@ public final class ActivityThread extends ClientTransactionHandler {
        }
    }

    /**
     * Dump heap info to proto.
     *
     * @param hasSwappedOutPss determines whether to use dirtySwap or dirtySwapPss
     */
    private static void dumpHeap(ProtoOutputStream proto, long fieldId, String name,
            int pss, int cleanPss, int sharedDirty, int privateDirty,
            int sharedClean, int privateClean,
            boolean hasSwappedOutPss, int dirtySwap, int dirtySwapPss) {
        final long token = proto.start(fieldId);

        proto.write(MemInfoProto.NativeProcess.MemoryInfo.NAME, name);
        proto.write(MemInfoProto.NativeProcess.MemoryInfo.TOTAL_PSS_KB, pss);
        proto.write(MemInfoProto.NativeProcess.MemoryInfo.CLEAN_PSS_KB, cleanPss);
        proto.write(MemInfoProto.NativeProcess.MemoryInfo.SHARED_DIRTY_KB, sharedDirty);
        proto.write(MemInfoProto.NativeProcess.MemoryInfo.PRIVATE_DIRTY_KB, privateDirty);
        proto.write(MemInfoProto.NativeProcess.MemoryInfo.SHARED_CLEAN_KB, sharedClean);
        proto.write(MemInfoProto.NativeProcess.MemoryInfo.PRIVATE_CLEAN_KB, privateClean);
        if (hasSwappedOutPss) {
            proto.write(MemInfoProto.NativeProcess.MemoryInfo.DIRTY_SWAP_PSS_KB, dirtySwapPss);
        } else {
            proto.write(MemInfoProto.NativeProcess.MemoryInfo.DIRTY_SWAP_KB, dirtySwap);
        }

        proto.end(token);
    }

    /**
     * Dump mem info data to proto.
     */
    public static void dumpMemInfoTable(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
            boolean dumpDalvik, boolean dumpSummaryOnly,
            long nativeMax, long nativeAllocated, long nativeFree,
            long dalvikMax, long dalvikAllocated, long dalvikFree) {

        if (!dumpSummaryOnly) {
            final long nhToken = proto.start(MemInfoProto.NativeProcess.NATIVE_HEAP);
            dumpHeap(proto, MemInfoProto.NativeProcess.HeapInfo.MEM_INFO, "Native Heap",
                    memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
                    memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
                    memInfo.nativePrivateClean, memInfo.hasSwappedOutPss,
                    memInfo.nativeSwappedOut, memInfo.nativeSwappedOutPss);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_SIZE_KB, nativeMax);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_ALLOC_KB, nativeAllocated);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_FREE_KB, nativeFree);
            proto.end(nhToken);

            final long dvToken = proto.start(MemInfoProto.NativeProcess.DALVIK_HEAP);
            dumpHeap(proto, MemInfoProto.NativeProcess.HeapInfo.MEM_INFO, "Dalvik Heap",
                    memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
                    memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
                    memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss,
                    memInfo.dalvikSwappedOut, memInfo.dalvikSwappedOutPss);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_SIZE_KB, dalvikMax);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_ALLOC_KB, dalvikAllocated);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_FREE_KB, dalvikFree);
            proto.end(dvToken);

            int otherPss = memInfo.otherPss;
            int otherSwappablePss = memInfo.otherSwappablePss;
            int otherSharedDirty = memInfo.otherSharedDirty;
            int otherPrivateDirty = memInfo.otherPrivateDirty;
            int otherSharedClean = memInfo.otherSharedClean;
            int otherPrivateClean = memInfo.otherPrivateClean;
            int otherSwappedOut = memInfo.otherSwappedOut;
            int otherSwappedOutPss = memInfo.otherSwappedOutPss;

            for (int i = 0; i < Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
                final int myPss = memInfo.getOtherPss(i);
                final int mySwappablePss = memInfo.getOtherSwappablePss(i);
                final int mySharedDirty = memInfo.getOtherSharedDirty(i);
                final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
                final int mySharedClean = memInfo.getOtherSharedClean(i);
                final int myPrivateClean = memInfo.getOtherPrivateClean(i);
                final int mySwappedOut = memInfo.getOtherSwappedOut(i);
                final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
                if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
                        || mySharedClean != 0 || myPrivateClean != 0
                        || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
                    dumpHeap(proto, MemInfoProto.NativeProcess.OTHER_HEAPS,
                            Debug.MemoryInfo.getOtherLabel(i),
                            myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
                            mySharedClean, myPrivateClean,
                            memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);

                    otherPss -= myPss;
                    otherSwappablePss -= mySwappablePss;
                    otherSharedDirty -= mySharedDirty;
                    otherPrivateDirty -= myPrivateDirty;
                    otherSharedClean -= mySharedClean;
                    otherPrivateClean -= myPrivateClean;
                    otherSwappedOut -= mySwappedOut;
                    otherSwappedOutPss -= mySwappedOutPss;
                }
            }

            dumpHeap(proto, MemInfoProto.NativeProcess.UNKNOWN_HEAP, "Unknown",
                    otherPss, otherSwappablePss,
                    otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
                    memInfo.hasSwappedOutPss, otherSwappedOut, otherSwappedOutPss);
            final long tToken = proto.start(MemInfoProto.NativeProcess.TOTAL_HEAP);
            dumpHeap(proto, MemInfoProto.NativeProcess.HeapInfo.MEM_INFO, "TOTAL",
                    memInfo.getTotalPss(), memInfo.getTotalSwappablePss(),
                    memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
                    memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
                    memInfo.hasSwappedOutPss, memInfo.getTotalSwappedOut(),
                    memInfo.getTotalSwappedOutPss());
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_SIZE_KB, nativeMax + dalvikMax);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_ALLOC_KB,
                    nativeAllocated + dalvikAllocated);
            proto.write(MemInfoProto.NativeProcess.HeapInfo.HEAP_FREE_KB, nativeFree + dalvikFree);
            proto.end(tToken);

            if (dumpDalvik) {
                for (int i = Debug.MemoryInfo.NUM_OTHER_STATS;
                        i < Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS;
                        i++) {
                    final int myPss = memInfo.getOtherPss(i);
                    final int mySwappablePss = memInfo.getOtherSwappablePss(i);
                    final int mySharedDirty = memInfo.getOtherSharedDirty(i);
                    final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
                    final int mySharedClean = memInfo.getOtherSharedClean(i);
                    final int myPrivateClean = memInfo.getOtherPrivateClean(i);
                    final int mySwappedOut = memInfo.getOtherSwappedOut(i);
                    final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
                    if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
                            || mySharedClean != 0 || myPrivateClean != 0
                            || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
                        dumpHeap(proto, MemInfoProto.NativeProcess.DALVIK_DETAILS,
                                Debug.MemoryInfo.getOtherLabel(i),
                                myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
                                mySharedClean, myPrivateClean,
                                memInfo.hasSwappedOutPss, mySwappedOut, mySwappedOutPss);
                    }
                }
            }
        }

        final long asToken = proto.start(MemInfoProto.NativeProcess.APP_SUMMARY);
        proto.write(MemInfoProto.NativeProcess.AppSummary.JAVA_HEAP_PSS_KB,
                memInfo.getSummaryJavaHeap());
        proto.write(MemInfoProto.NativeProcess.AppSummary.NATIVE_HEAP_PSS_KB,
                memInfo.getSummaryNativeHeap());
        proto.write(MemInfoProto.NativeProcess.AppSummary.CODE_PSS_KB, memInfo.getSummaryCode());
        proto.write(MemInfoProto.NativeProcess.AppSummary.STACK_PSS_KB, memInfo.getSummaryStack());
        proto.write(MemInfoProto.NativeProcess.AppSummary.GRAPHICS_PSS_KB,
                memInfo.getSummaryGraphics());
        proto.write(MemInfoProto.NativeProcess.AppSummary.PRIVATE_OTHER_PSS_KB,
                memInfo.getSummaryPrivateOther());
        proto.write(MemInfoProto.NativeProcess.AppSummary.SYSTEM_PSS_KB,
                memInfo.getSummarySystem());
        if (memInfo.hasSwappedOutPss) {
            proto.write(MemInfoProto.NativeProcess.AppSummary.TOTAL_SWAP_PSS,
                    memInfo.getSummaryTotalSwapPss());
        } else {
            proto.write(MemInfoProto.NativeProcess.AppSummary.TOTAL_SWAP_PSS,
                    memInfo.getSummaryTotalSwap());
        }
        proto.end(asToken);
    }

    public void registerOnActivityPausedListener(Activity activity,
            OnActivityPausedListener listener) {
        synchronized (mOnPauseListeners) {
+5 −0
Original line number Diff line number Diff line
@@ -164,4 +164,9 @@ message IncidentProto {
        (section).type = SECTION_DUMPSYS,
        (section).args = "window --proto"
    ];

    optional com.android.server.am.proto.MemInfoProto meminfo = 3018 [
        (section).type = SECTION_DUMPSYS,
        (section).args = "meminfo --proto"
    ];
}
+67 −4
Original line number Diff line number Diff line
@@ -16,16 +16,16 @@

syntax = "proto2";

package com.android.server.am.proto;

import "frameworks/base/core/proto/android/app/notification.proto";
import "frameworks/base/core/proto/android/content/intent.proto";
import "frameworks/base/core/proto/android/server/intentresolver.proto";
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
import "frameworks/base/core/proto/android/graphics/rect.proto";
import "frameworks/base/core/proto/android/os/looper.proto";
import "frameworks/base/core/proto/android/server/intentresolver.proto";
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
import "frameworks/base/core/proto/android/util/common.proto";

package com.android.server.am.proto;

option java_multiple_files = true;

message ActivityManagerServiceProto {
@@ -159,6 +159,69 @@ message BroadcastQueueProto {
  repeated BroadcastSummary historical_broadcasts_summary = 6;
}

message MemInfoProto {
  optional int64 uptime_duration_ms = 1;
  optional int64 elapsed_realtime_ms = 2;

  message NativeProcess {
    optional int32 pid = 1;
    optional string process_name = 2;

    message MemoryInfo {
      optional string name = 1;
      // The proportional set size for the heap.
      optional int32 total_pss_kb = 2;
      // The proportional set size that is swappable for the heap.
      optional int32 clean_pss_kb = 3;
      // The private dirty pages used by the heap.
      optional int32 shared_dirty_kb = 4;
      // The shared dirty pages used by the heap.
      optional int32 private_dirty_kb = 5;
      // The shared clean pages used by the heap.
      optional int32 shared_clean_kb = 6;
      // The private clean pages used by the heap.
      optional int32 private_clean_kb = 7;
      oneof dirty_swap {
        // The dirty the pages that have been swapped out.
        int32 dirty_swap_kb = 8;
        // The dirty the pages that have been swapped out, proportional.
        int32 dirty_swap_pss_kb = 9;
      }
    }
    message HeapInfo {
      optional MemoryInfo mem_info = 1;
      optional int32 heap_size_kb = 2;
      optional int32 heap_alloc_kb = 3;
      optional int32 heap_free_kb = 4;
    }
    optional HeapInfo native_heap = 3;
    optional HeapInfo dalvik_heap = 4;
    repeated MemoryInfo other_heaps = 5;
    optional HeapInfo unknown_heap = 6;
    // Summation of native_heap, dalvik_heap, and other_heaps.
    optional HeapInfo total_heap = 7;

    repeated MemoryInfo dalvik_details = 8;

    message AppSummary {
      optional int32 java_heap_pss_kb = 1;
      optional int32 native_heap_pss_kb = 2;
      optional int32 code_pss_kb = 3;
      optional int32 stack_pss_kb = 4;
      optional int32 graphics_pss_kb = 5;
      optional int32 private_other_pss_kb = 6;
      optional int32 system_pss_kb = 7;

      oneof total_swap {
        int32 total_swap_pss = 8;
        int32 total_swap_kb = 9;
      }
    }
    optional AppSummary app_summary = 9;
  }
  repeated NativeProcess native_processes = 3;
}

message StickyBroadcastProto {
  optional int32 user = 1;

+123 −56
Original line number Diff line number Diff line
@@ -417,6 +417,7 @@ import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.am.proto.ActivityManagerServiceProto;
import com.android.server.am.proto.BroadcastProto;
import com.android.server.am.proto.GrantUriProto;
import com.android.server.am.proto.MemInfoProto;
import com.android.server.am.proto.NeededUriGrantsProto;
import com.android.server.am.proto.StickyBroadcastProto;
import com.android.server.firewall.IntentFirewall;
@@ -2569,14 +2570,13 @@ public class ActivityManagerService extends IActivityManager.Stub
            @Override
            public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args,
                    boolean asProto) {
                if (asProto) return;
                mActivityManagerService.dumpApplicationMemoryUsage(fd,
                        pw, "  ", new String[] {"-a"}, false, null);
                dump(fd, pw, new String[] {"-a"}, asProto);
            }
            @Override
            public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
                if (asProto) return;
                mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
                mActivityManagerService.dumpApplicationMemoryUsage(
                        fd, pw, "  ", args, false, null, asProto);
            }
        };
@@ -17207,8 +17207,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        boolean dumpProto;
    }
    final void dumpApplicationMemoryUsage(FileDescriptor fd,
            PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) {
    final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
            String[] args, boolean brief, PrintWriter categoryPw, boolean asProto) {
        MemoryUsageDumpOptions opts = new MemoryUsageDumpOptions();
        opts.dumpDetails = false;
        opts.dumpFullDetails = false;
@@ -17221,7 +17221,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        opts.packages = false;
        opts.isCheckinRequest = false;
        opts.dumpSwapPss = false;
        opts.dumpProto = false;
        opts.dumpProto = asProto;
        int opti = 0;
        while (opti < args.length) {
@@ -17289,7 +17289,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
    private final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix,
            MemoryUsageDumpOptions opts, String[] innerArgs, boolean brief,
            ArrayList<ProcessRecord> procs, PrintWriter categoryPw) {
        long uptime = SystemClock.uptimeMillis();
@@ -17298,7 +17298,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (procs == null) {
            // No Java processes.  Maybe they want to print a native process.
            if (innerArgs.length > 0 && innerArgs[0].charAt(0) != '-') {
            String proc = "N/A";
            if (innerArgs.length > 0) {
                proc = innerArgs[0];
                if (proc.charAt(0) != '-') {
                    ArrayList<ProcessCpuTracker.Stats> nativeProcs
                            = new ArrayList<ProcessCpuTracker.Stats>();
                    updateCpuStatsNow();
@@ -17318,8 +17321,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                        }
                    }
                    if (nativeProcs.size() > 0) {
                    dumpApplicationMemoryUsageHeader(pw, uptime, realtime, opts.isCheckinRequest,
                            opts.isCompact);
                        dumpApplicationMemoryUsageHeader(pw, uptime, realtime,
                                opts.isCheckinRequest, opts.isCompact);
                        Debug.MemoryInfo mi = null;
                        for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) {
                            final ProcessCpuTracker.Stats r = nativeProcs.get(i);
@@ -17336,8 +17339,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                                mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
                                mi.dalvikPrivateDirty = (int)tmpLong[0];
                            }
                        ActivityThread.dumpMemInfoTable(pw, mi, opts.isCheckinRequest, opts.dumpFullDetails,
                                opts.dumpDalvik, opts.dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0);
                            ActivityThread.dumpMemInfoTable(pw, mi, opts.isCheckinRequest,
                                    opts.dumpFullDetails, opts.dumpDalvik, opts.dumpSummaryOnly,
                                    pid, r.baseName, 0, 0, 0, 0, 0, 0);
                            if (opts.isCheckinRequest) {
                                pw.println();
                            }
@@ -17345,7 +17349,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                        return;
                    }
                }
            pw.println("No process found for: " + innerArgs[0]);
            }
            pw.println("No process found for: " + proc);
            return;
        }
@@ -17768,15 +17773,77 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw,
    private final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw,
            MemoryUsageDumpOptions opts, String[] innerArgs, boolean brief,
            ArrayList<ProcessRecord> procs) {
        final long uptimeMs = SystemClock.uptimeMillis();
        final long realtimeMs = SystemClock.elapsedRealtime();
        final long[] tmpLong = new long[1];
        if (procs == null) {
            // No Java processes.  Maybe they want to print a native process.
            String proc = "N/A";
            if (innerArgs.length > 0) {
                proc = innerArgs[0];
                if (proc.charAt(0) != '-') {
                    ArrayList<ProcessCpuTracker.Stats> nativeProcs
                            = new ArrayList<ProcessCpuTracker.Stats>();
                    updateCpuStatsNow();
                    int findPid = -1;
                    try {
                        findPid = Integer.parseInt(innerArgs[0]);
                    } catch (NumberFormatException e) {
                    }
                    synchronized (mProcessCpuTracker) {
                        final int N = mProcessCpuTracker.countStats();
                        for (int i=0; i<N; i++) {
                            ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
                            if (st.pid == findPid || (st.baseName != null
                                    && st.baseName.equals(innerArgs[0]))) {
                                nativeProcs.add(st);
                            }
                        }
                    }
                    if (nativeProcs.size() > 0) {
                        ProtoOutputStream proto = new ProtoOutputStream(fd);
        // TODO: implement
        pw.println("Not yet implemented. Have a cookie instead! :]");
                        proto.write(MemInfoProto.UPTIME_DURATION_MS, uptimeMs);
                        proto.write(MemInfoProto.ELAPSED_REALTIME_MS, realtimeMs);
                        Debug.MemoryInfo mi = null;
                        for (int i = nativeProcs.size() - 1 ; i >= 0 ; i--) {
                            final ProcessCpuTracker.Stats r = nativeProcs.get(i);
                            final int pid = r.pid;
                            final long nToken = proto.start(MemInfoProto.NATIVE_PROCESSES);
                            proto.write(MemInfoProto.NativeProcess.PID, pid);
                            proto.write(MemInfoProto.NativeProcess.PROCESS_NAME, r.baseName);
                            if (mi == null) {
                                mi = new Debug.MemoryInfo();
                            }
                            if (opts.dumpDetails || (!brief && !opts.oomOnly)) {
                                Debug.getMemoryInfo(pid, mi);
                            } else {
                                mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
                                mi.dalvikPrivateDirty = (int)tmpLong[0];
                            }
                            ActivityThread.dumpMemInfoTable(proto, mi, opts.dumpDalvik,
                                    opts.dumpSummaryOnly, 0, 0, 0, 0, 0, 0);
                            proto.end(nToken);
                        }
                        proto.flush();
                        return;
                    }
                }
            }
            Log.d(TAG, "No process found for: " + innerArgs[0]);
            return;
        }
        // TODO: finish
        pw.println("Java processes aren't implemented yet. Have a coffee instead! :]");
    }
    private void appendBasicMemEntry(StringBuilder sb, int oomAdj, int procState, long pss,