Merge "incidentd: dumping native process mem info to proto."

This commit is contained in:
TreeHugger Robot
2017-11-30 19:58:15 +00:00
committed by Android (Google) Code Review
4 changed files with 358 additions and 60 deletions

View File

@@ -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) {

View File

@@ -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"
];
}

View File

@@ -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;

View File

@@ -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,54 +17298,59 @@ 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) != '-') {
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);
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) {
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);
final int pid = r.pid;
if (!opts.isCheckinRequest && opts.dumpDetails) {
pw.println("\n** MEMINFO in pid " + pid + " [" + 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(pw, mi, opts.isCheckinRequest, opts.dumpFullDetails,
opts.dumpDalvik, opts.dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0);
if (opts.isCheckinRequest) {
pw.println();
if (nativeProcs.size() > 0) {
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);
final int pid = r.pid;
if (!opts.isCheckinRequest && opts.dumpDetails) {
pw.println("\n** MEMINFO in pid " + pid + " [" + 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(pw, mi, opts.isCheckinRequest,
opts.dumpFullDetails, opts.dumpDalvik, opts.dumpSummaryOnly,
pid, r.baseName, 0, 0, 0, 0, 0, 0);
if (opts.isCheckinRequest) {
pw.println();
}
}
return;
}
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) {
ProtoOutputStream proto = new ProtoOutputStream(fd);
final long uptimeMs = SystemClock.uptimeMillis();
final long realtimeMs = SystemClock.elapsedRealtime();
final long[] tmpLong = new long[1];
// TODO: implement
pw.println("Not yet implemented. Have a cookie instead! :]");
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);
proto.flush();
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,