Add dumpsys meminfo --unreachable
dumpsys meminfo --unreachable will search the native heap for
allocations that are unreachable.
Bug: 27208635
Change-Id: I40ab1c261cb222ca71d04ab8408f355bcb18ed94
(cherry picked from commit 84b1e3554b36b7fbccf57330c93bf484985ae3d6)
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 04883a9..0990660 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -977,18 +977,19 @@
@Override
public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
- boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) {
+ boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+ boolean dumpUnreachable, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
- dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly);
+ dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
} finally {
pw.flush();
}
}
private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
- boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly) {
+ boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -1102,6 +1103,16 @@
pw.println(" Asset Allocations");
pw.print(assetAlloc);
}
+
+ // Unreachable native memory
+ if (dumpUnreachable) {
+ boolean showContents = ((mBoundApplication != null)
+ && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
+ || android.os.Build.IS_DEBUGGABLE;
+ pw.println(" ");
+ pw.println(" Unreachable memory");
+ pw.print(Debug.getUnreachableMemory(100, showContents));
+ }
}
@Override
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 59ecc03..744ddf7 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -548,11 +548,12 @@
boolean dumpInfo = data.readInt() != 0;
boolean dumpDalvik = data.readInt() != 0;
boolean dumpSummaryOnly = data.readInt() != 0;
+ boolean dumpUnreachable = data.readInt() != 0;
String[] args = data.readStringArray();
if (fd != null) {
try {
dumpMemInfo(fd.getFileDescriptor(), mi, checkin, dumpInfo,
- dumpDalvik, dumpSummaryOnly, args);
+ dumpDalvik, dumpSummaryOnly, dumpUnreachable, args);
} finally {
try {
fd.close();
@@ -1328,7 +1329,8 @@
}
public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
- boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException {
+ boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+ boolean dumpUnreachable, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -1338,6 +1340,7 @@
data.writeInt(dumpInfo ? 1 : 0);
data.writeInt(dumpDalvik ? 1 : 0);
data.writeInt(dumpSummaryOnly ? 1 : 0);
+ data.writeInt(dumpUnreachable ? 1 : 0);
data.writeStringArray(args);
mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index b55da88..a3c9591 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -133,7 +133,8 @@
void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
void scheduleTrimMemory(int level) throws RemoteException;
void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, boolean dumpInfo,
- boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException;
+ boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
+ String[] args) throws RemoteException;
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
void unstableProviderDied(IBinder provider) throws RemoteException;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e58744b..a04e8d2 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2158,6 +2158,14 @@
public static native void dumpNativeBacktraceToFile(int pid, String file);
/**
+ * Get description of unreachable native memory.
+ * @param limit the number of leaks to provide info on, 0 to only get a summary.
+ * @param contents true to include a hex dump of the contents of unreachable memory.
+ * @return the String containing a description of unreachable memory.
+ * @hide */
+ public static native String getUnreachableMemory(int limit, boolean contents);
+
+ /**
* Return a String describing the calling method and location at a particular stack depth.
* @param callStack the Thread stack
* @param depth the depth of stack to return information for.
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 1b6b53a..7f458e5 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -260,7 +260,8 @@
libprocessgroup \
libnativebridge \
libradio_metadata \
- libnativeloader
+ libnativeloader \
+ libmemunreachable \
LOCAL_SHARED_LIBRARIES += \
libhwui \
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 03a1e71..3df0876 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -21,6 +21,7 @@
#include "utils/misc.h"
#include "cutils/debugger.h"
#include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
#include <cutils/log.h>
#include <fcntl.h>
@@ -36,6 +37,9 @@
#include <ctype.h>
#include <malloc.h>
+#include <iomanip>
+#include <string>
+
namespace android
{
@@ -1023,6 +1027,13 @@
close(fd);
}
+static jstring android_os_Debug_getUnreachableMemory(JNIEnv* env, jobject clazz,
+ jint limit, jboolean contents)
+{
+ std::string s = GetUnreachableMemoryString(contents, limit);
+ return env->NewStringUTF(s.c_str());
+}
+
/*
* JNI registration.
*/
@@ -1058,6 +1069,8 @@
(void*)android_os_Debug_getDeathObjectCount },
{ "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
(void*)android_os_Debug_dumpNativeBacktraceToFile },
+ { "getUnreachableMemory", "(IZ)Ljava/lang/String;",
+ (void*)android_os_Debug_getUnreachableMemory },
};
int register_android_os_Debug(JNIEnv *env)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 337f749..6e9faeb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15100,6 +15100,7 @@
boolean dumpFullDetails = false;
boolean dumpDalvik = false;
boolean dumpSummaryOnly = false;
+ boolean dumpUnreachable = false;
boolean oomOnly = false;
boolean isCompact = false;
boolean localOnly = false;
@@ -15128,6 +15129,8 @@
dumpSummaryOnly = true;
} else if ("-S".equals(opt)) {
dumpSwapPss = true;
+ } else if ("--unreachable".equals(opt)) {
+ dumpUnreachable = true;
} else if ("--oom".equals(opt)) {
oomOnly = true;
} else if ("--local".equals(opt)) {
@@ -15289,7 +15292,7 @@
try {
pw.flush();
thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
- dumpDalvik, dumpSummaryOnly, innerArgs);
+ dumpDalvik, dumpSummaryOnly, dumpUnreachable, innerArgs);
} catch (RemoteException e) {
if (!isCheckinRequest) {
pw.println("Got RemoteException!");