summaryrefslogtreecommitdiff
path: root/core/jni/android_os_Debug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/jni/android_os_Debug.cpp')
-rw-r--r--core/jni/android_os_Debug.cpp293
1 files changed, 34 insertions, 259 deletions
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index a98f94722326..3c2dccd451d4 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -16,97 +16,51 @@
#define LOG_TAG "android.os.Debug"
+#include "android_os_Debug.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
#include <assert.h>
+#include <binderdebug/BinderDebug.h>
+#include <bionic/malloc.h>
#include <ctype.h>
+#include <debuggerd/client.h>
+#include <dmabufinfo/dmabuf_sysfs_stats.h>
+#include <dmabufinfo/dmabufinfo.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <log/log.h>
#include <malloc.h>
+#include <meminfo/androidprocheaps.h>
+#include <meminfo/procmeminfo.h>
+#include <meminfo/sysmeminfo.h>
+#include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
+#include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
+#include <utils/String8.h>
+#include <utils/misc.h>
+#include <vintf/KernelConfigs.h>
#include <iomanip>
#include <string>
#include <vector>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <bionic/malloc.h>
-#include <debuggerd/client.h>
-#include <log/log.h>
-#include <utils/misc.h>
-#include <utils/String8.h>
-
-#include <nativehelper/JNIPlatformHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
#include "jni.h"
-#include <dmabufinfo/dmabuf_sysfs_stats.h>
-#include <dmabufinfo/dmabufinfo.h>
-#include <meminfo/procmeminfo.h>
-#include <meminfo/sysmeminfo.h>
-#include <memtrack/memtrack.h>
-#include <memunreachable/memunreachable.h>
-#include <android-base/strings.h>
-#include "android_os_Debug.h"
-#include <vintf/KernelConfigs.h>
namespace android
{
-enum {
- HEAP_UNKNOWN,
- HEAP_DALVIK,
- HEAP_NATIVE,
-
- HEAP_DALVIK_OTHER,
- HEAP_STACK,
- HEAP_CURSOR,
- HEAP_ASHMEM,
- HEAP_GL_DEV,
- HEAP_UNKNOWN_DEV,
- HEAP_SO,
- HEAP_JAR,
- HEAP_APK,
- HEAP_TTF,
- HEAP_DEX,
- HEAP_OAT,
- HEAP_ART,
- HEAP_UNKNOWN_MAP,
- HEAP_GRAPHICS,
- HEAP_GL,
- HEAP_OTHER_MEMTRACK,
-
- // Dalvik extra sections (heap).
- HEAP_DALVIK_NORMAL,
- HEAP_DALVIK_LARGE,
- HEAP_DALVIK_ZYGOTE,
- HEAP_DALVIK_NON_MOVING,
-
- // Dalvik other extra sections.
- HEAP_DALVIK_OTHER_LINEARALLOC,
- HEAP_DALVIK_OTHER_ACCOUNTING,
- HEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE,
- HEAP_DALVIK_OTHER_APP_CODE_CACHE,
- HEAP_DALVIK_OTHER_COMPILER_METADATA,
- HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE,
-
- // Boot vdex / app dex / app vdex
- HEAP_DEX_BOOT_VDEX,
- HEAP_DEX_APP_DEX,
- HEAP_DEX_APP_VDEX,
-
- // App art, boot art.
- HEAP_ART_APP,
- HEAP_ART_BOOT,
-
- _NUM_HEAP,
- _NUM_EXCLUSIVE_HEAP = HEAP_OTHER_MEMTRACK+1,
- _NUM_CORE_HEAP = HEAP_NATIVE+1
-};
+using namespace android::meminfo;
struct stat_fields {
jfieldID pss_field;
@@ -146,18 +100,6 @@ static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
static jfieldID otherStats_field;
static jfieldID hasSwappedOutPss_field;
-struct stats_t {
- int pss;
- int swappablePss;
- int rss;
- int privateDirty;
- int sharedDirty;
- int privateClean;
- int sharedClean;
- int swappedOut;
- int swappedOutPss;
-};
-
#define BINDER_STATS "/proc/binder/stats"
static jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz)
@@ -240,190 +182,14 @@ static int read_memtrack_memory(int pid, struct graphics_memory_pss* graphics_me
return err;
}
-static bool load_maps(int pid, stats_t* stats, bool* foundSwapPss)
-{
- *foundSwapPss = false;
- uint64_t prev_end = 0;
- int prev_heap = HEAP_UNKNOWN;
-
- std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
- auto vma_scan = [&](const meminfo::Vma& vma) {
- int which_heap = HEAP_UNKNOWN;
- int sub_heap = HEAP_UNKNOWN;
- bool is_swappable = false;
- std::string name;
- if (base::EndsWith(vma.name, " (deleted)")) {
- name = vma.name.substr(0, vma.name.size() - strlen(" (deleted)"));
- } else {
- name = vma.name;
- }
-
- uint32_t namesz = name.size();
- if (base::StartsWith(name, "[heap]")) {
- which_heap = HEAP_NATIVE;
- } else if (base::StartsWith(name, "[anon:libc_malloc]")) {
- which_heap = HEAP_NATIVE;
- } else if (base::StartsWith(name, "[anon:scudo:")) {
- which_heap = HEAP_NATIVE;
- } else if (base::StartsWith(name, "[anon:GWP-ASan")) {
- which_heap = HEAP_NATIVE;
- } else if (base::StartsWith(name, "[stack")) {
- which_heap = HEAP_STACK;
- } else if (base::StartsWith(name, "[anon:stack_and_tls:")) {
- which_heap = HEAP_STACK;
- } else if (base::EndsWith(name, ".so")) {
- which_heap = HEAP_SO;
- is_swappable = true;
- } else if (base::EndsWith(name, ".jar")) {
- which_heap = HEAP_JAR;
- is_swappable = true;
- } else if (base::EndsWith(name, ".apk")) {
- which_heap = HEAP_APK;
- is_swappable = true;
- } else if (base::EndsWith(name, ".ttf")) {
- which_heap = HEAP_TTF;
- is_swappable = true;
- } else if ((base::EndsWith(name, ".odex")) ||
- (namesz > 4 && strstr(name.c_str(), ".dex") != nullptr)) {
- which_heap = HEAP_DEX;
- sub_heap = HEAP_DEX_APP_DEX;
- is_swappable = true;
- } else if (base::EndsWith(name, ".vdex")) {
- which_heap = HEAP_DEX;
- // Handle system@framework@boot and system/framework/boot|apex
- if ((strstr(name.c_str(), "@boot") != nullptr) ||
- (strstr(name.c_str(), "/boot") != nullptr) ||
- (strstr(name.c_str(), "/apex") != nullptr)) {
- sub_heap = HEAP_DEX_BOOT_VDEX;
- } else {
- sub_heap = HEAP_DEX_APP_VDEX;
- }
- is_swappable = true;
- } else if (base::EndsWith(name, ".oat")) {
- which_heap = HEAP_OAT;
- is_swappable = true;
- } else if (base::EndsWith(name, ".art") || base::EndsWith(name, ".art]")) {
- which_heap = HEAP_ART;
- // Handle system@framework@boot* and system/framework/boot|apex*
- if ((strstr(name.c_str(), "@boot") != nullptr) ||
- (strstr(name.c_str(), "/boot") != nullptr) ||
- (strstr(name.c_str(), "/apex") != nullptr)) {
- sub_heap = HEAP_ART_BOOT;
- } else {
- sub_heap = HEAP_ART_APP;
- }
- is_swappable = true;
- } else if (base::StartsWith(name, "/dev/")) {
- which_heap = HEAP_UNKNOWN_DEV;
- if (base::StartsWith(name, "/dev/kgsl-3d0")) {
- which_heap = HEAP_GL_DEV;
- } else if (base::StartsWith(name, "/dev/ashmem/CursorWindow")) {
- which_heap = HEAP_CURSOR;
- } else if (base::StartsWith(name, "/dev/ashmem/jit-zygote-cache")) {
- which_heap = HEAP_DALVIK_OTHER;
- sub_heap = HEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE;
- } else if (base::StartsWith(name, "/dev/ashmem")) {
- which_heap = HEAP_ASHMEM;
- }
- } else if (base::StartsWith(name, "/memfd:jit-cache")) {
- which_heap = HEAP_DALVIK_OTHER;
- sub_heap = HEAP_DALVIK_OTHER_APP_CODE_CACHE;
- } else if (base::StartsWith(name, "/memfd:jit-zygote-cache")) {
- which_heap = HEAP_DALVIK_OTHER;
- sub_heap = HEAP_DALVIK_OTHER_ZYGOTE_CODE_CACHE;
- } else if (base::StartsWith(name, "[anon:")) {
- which_heap = HEAP_UNKNOWN;
- if (base::StartsWith(name, "[anon:dalvik-")) {
- which_heap = HEAP_DALVIK_OTHER;
- if (base::StartsWith(name, "[anon:dalvik-LinearAlloc")) {
- sub_heap = HEAP_DALVIK_OTHER_LINEARALLOC;
- } else if (base::StartsWith(name, "[anon:dalvik-alloc space") ||
- base::StartsWith(name, "[anon:dalvik-main space")) {
- // This is the regular Dalvik heap.
- which_heap = HEAP_DALVIK;
- sub_heap = HEAP_DALVIK_NORMAL;
- } else if (base::StartsWith(name,
- "[anon:dalvik-large object space") ||
- base::StartsWith(
- name, "[anon:dalvik-free list large object space")) {
- which_heap = HEAP_DALVIK;
- sub_heap = HEAP_DALVIK_LARGE;
- } else if (base::StartsWith(name, "[anon:dalvik-non moving space")) {
- which_heap = HEAP_DALVIK;
- sub_heap = HEAP_DALVIK_NON_MOVING;
- } else if (base::StartsWith(name, "[anon:dalvik-zygote space")) {
- which_heap = HEAP_DALVIK;
- sub_heap = HEAP_DALVIK_ZYGOTE;
- } else if (base::StartsWith(name, "[anon:dalvik-indirect ref")) {
- sub_heap = HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE;
- } else if (base::StartsWith(name, "[anon:dalvik-jit-code-cache") ||
- base::StartsWith(name, "[anon:dalvik-data-code-cache")) {
- sub_heap = HEAP_DALVIK_OTHER_APP_CODE_CACHE;
- } else if (base::StartsWith(name, "[anon:dalvik-CompilerMetadata")) {
- sub_heap = HEAP_DALVIK_OTHER_COMPILER_METADATA;
- } else {
- sub_heap = HEAP_DALVIK_OTHER_ACCOUNTING; // Default to accounting.
- }
- }
- } else if (namesz > 0) {
- which_heap = HEAP_UNKNOWN_MAP;
- } else if (vma.start == prev_end && prev_heap == HEAP_SO) {
- // bss section of a shared library
- which_heap = HEAP_SO;
- }
-
- prev_end = vma.end;
- prev_heap = which_heap;
-
- const meminfo::MemUsage& usage = vma.usage;
- if (usage.swap_pss > 0 && *foundSwapPss != true) {
- *foundSwapPss = true;
- }
-
- uint64_t swapable_pss = 0;
- if (is_swappable && (usage.pss > 0)) {
- float sharing_proportion = 0.0;
- if ((usage.shared_clean > 0) || (usage.shared_dirty > 0)) {
- sharing_proportion = (usage.pss - usage.uss) / (usage.shared_clean + usage.shared_dirty);
- }
- swapable_pss = (sharing_proportion * usage.shared_clean) + usage.private_clean;
- }
-
- stats[which_heap].pss += usage.pss;
- stats[which_heap].swappablePss += swapable_pss;
- stats[which_heap].rss += usage.rss;
- stats[which_heap].privateDirty += usage.private_dirty;
- stats[which_heap].sharedDirty += usage.shared_dirty;
- stats[which_heap].privateClean += usage.private_clean;
- stats[which_heap].sharedClean += usage.shared_clean;
- stats[which_heap].swappedOut += usage.swap;
- stats[which_heap].swappedOutPss += usage.swap_pss;
- if (which_heap == HEAP_DALVIK || which_heap == HEAP_DALVIK_OTHER ||
- which_heap == HEAP_DEX || which_heap == HEAP_ART) {
- stats[sub_heap].pss += usage.pss;
- stats[sub_heap].swappablePss += swapable_pss;
- stats[sub_heap].rss += usage.rss;
- stats[sub_heap].privateDirty += usage.private_dirty;
- stats[sub_heap].sharedDirty += usage.shared_dirty;
- stats[sub_heap].privateClean += usage.private_clean;
- stats[sub_heap].sharedClean += usage.shared_clean;
- stats[sub_heap].swappedOut += usage.swap;
- stats[sub_heap].swappedOutPss += usage.swap_pss;
- }
- return true;
- };
-
- return meminfo::ForEachVmaFromFile(smaps_path, vma_scan);
-}
-
static jboolean android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
jint pid, jobject object)
{
bool foundSwapPss;
- stats_t stats[_NUM_HEAP];
+ AndroidHeapStats stats[_NUM_HEAP];
memset(&stats, 0, sizeof(stats));
- if (!load_maps(pid, stats, &foundSwapPss)) {
+ if (!ExtractAndroidHeapStats(pid, stats, &foundSwapPss)) {
return JNI_FALSE;
}
@@ -815,6 +581,15 @@ static bool dumpTraces(JNIEnv* env, jint pid, jstring fileName, jint timeoutSecs
return false;
}
+ std::string binderState;
+ android::status_t status = android::getBinderTransactions(pid, binderState);
+ if (status == android::OK) {
+ if (!android::base::WriteStringToFd(binderState, fd)) {
+ PLOG(ERROR) << "Failed to dump binder state info for pid: " << pid;
+ }
+ } else {
+ PLOG(ERROR) << "Failed to get binder state info for pid: " << pid << " status: " << status;
+ }
int res = dump_backtrace_to_file_timeout(pid, dumpType, timeoutSecs, fd);
if (fdatasync(fd.get()) != 0) {
PLOG(ERROR) << "Failed flushing trace.";