android_os_Debug.cpp revision b437e090ec03a2bab10bdfcb9484577a7f34e157
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define LOG_TAG "android.os.Debug" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h" 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <time.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h> 2806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <errno.h> 2906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <assert.h> 300e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn#include <ctype.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <malloc.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 390e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornenum { 400e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_UNKNOWN, 410e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_DALVIK, 420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_NATIVE, 430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_CURSOR, 440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_ASHMEM, 450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_UNKNOWN_DEV, 460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_SO, 470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_JAR, 480e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_APK, 490e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_TTF, 500e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_DEX, 510e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn HEAP_UNKNOWN_MAP, 520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn _NUM_HEAP, 540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn _NUM_CORE_HEAP = HEAP_NATIVE+1 550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn}; 560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstruct stat_fields { 580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn jfieldID pss_field; 590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn jfieldID privateDirty_field; 600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn jfieldID sharedDirty_field; 610e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn}; 620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstruct stat_field_names { 640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn const char* pss_name; 650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn const char* privateDirty_name; 660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn const char* sharedDirty_name; 670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn}; 680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic stat_fields stat_fields[_NUM_CORE_HEAP]; 700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic stat_field_names stat_field_names[_NUM_CORE_HEAP] = { 720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn { "otherPss", "otherPrivateDirty", "otherSharedDirty" }, 730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn { "dalvikPss", "dalvikPrivateDirty", "dalvikSharedDirty" }, 740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn { "nativePss", "nativePrivateDirty", "nativeSharedDirty" } 750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn}; 760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne HackbornjfieldID otherStats_field; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct stats_t { 800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int pss; 810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int privateDirty; 820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int sharedDirty; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BINDER_STATS "/proc/binder/stats" 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz) 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct mallinfo info = mallinfo(); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jlong) info.usmblks; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz) 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct mallinfo info = mallinfo(); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jlong) info.uordblks; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz) 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct mallinfo info = mallinfo(); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jlong) info.fordblks; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void read_mapinfo(FILE *fp, stats_t* stats) 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char line[1024]; 1200e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int len, nameLen; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool skip, done = false; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1230e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn unsigned size = 0, resident = 0, pss = 0; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned shared_clean = 0, shared_dirty = 0; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned private_clean = 0, private_dirty = 0; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned referenced = 0; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned temp; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1290e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn unsigned long int start; 1300e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn unsigned long int end = 0; 1310e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn unsigned long int prevEnd = 0; 1320e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn char* name; 1330e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int name_pos; 1340e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 1350e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int whichHeap = HEAP_UNKNOWN; 1360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int prevHeap = HEAP_UNKNOWN; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1380e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn if(fgets(line, sizeof(line), fp) == 0) return; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!done) { 1410e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn prevHeap = whichHeap; 1420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn prevEnd = end; 1430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_UNKNOWN; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skip = false; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = strlen(line); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len < 1) return; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project line[--len] = 0; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1500e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) { 1510e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn skip = true; 1520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else { 1530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn while (isspace(line[name_pos])) { 1540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn name_pos += 1; 1550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 1560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn name = line + name_pos; 1570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn nameLen = strlen(name); 1580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 1590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn if (strstr(name, "[heap]") == name) { 1600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_NATIVE; 1610e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (strstr(name, "/dev/ashmem/dalvik-") == name) { 1620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_DALVIK; 1630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (strstr(name, "/dev/ashmem/CursorWindow") == name) { 1640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_CURSOR; 1650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (strstr(name, "/dev/ashmem/") == name) { 1660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_ASHMEM; 1670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (strstr(name, "/dev/") == name) { 1680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_UNKNOWN_DEV; 1690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) { 1700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_SO; 1710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) { 1720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_JAR; 1730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) { 1740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_APK; 1750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) { 1760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_TTF; 1770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) { 1780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_DEX; 1790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (nameLen > 0) { 1800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_UNKNOWN_MAP; 1810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } else if (start == prevEnd && prevHeap == HEAP_SO) { 1820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn // bss section of a shared library. 1830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn whichHeap = HEAP_SO; 1840e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap, 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // isSqliteHeap, line); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fgets(line, 1024, fp) == 0) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project done = true; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sscanf(line, "Size: %d kB", &temp) == 1) { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = temp; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Rss: %d kB", &temp) == 1) { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resident = temp; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Pss: %d kB", &temp) == 1) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pss = temp; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project shared_clean = temp; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project shared_dirty = temp; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private_clean = temp; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private_dirty = temp; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sscanf(line, "Referenced: %d kB", &temp) == 1) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project referenced = temp; 212bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // looks like a new mapping 214bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba // example: "10000000-10001000 ---p 10000000 00:00 0" 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!skip) { 2200e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats[whichHeap].pss += pss; 2210e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats[whichHeap].privateDirty += private_dirty; 2220e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats[whichHeap].sharedDirty += shared_dirty; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void load_maps(int pid, stats_t* stats) 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char tmp[128]; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FILE *fp; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(tmp, "/proc/%d/smaps", pid); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fp = fopen(tmp, "r"); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fp == 0) return; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project read_mapinfo(fp, stats); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fclose(fp); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2403025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, 2413025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn jint pid, jobject object) 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats_t stats[_NUM_HEAP]; 2440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn memset(&stats, 0, sizeof(stats)); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn load_maps(pid, stats); 2470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 2480e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) { 2490e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats[HEAP_UNKNOWN].pss += stats[i].pss; 2500e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty; 2510e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty; 2520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn for (int i=0; i<_NUM_CORE_HEAP; i++) { 2550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss); 2560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty); 2570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty); 2580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0); 2630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn if (otherArray == NULL) { 2640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn return; 2650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 2660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 2670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn int j=0; 2680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) { 2690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn otherArray[j++] = stats[i].pss; 2700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn otherArray[j++] = stats[i].privateDirty; 2710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn otherArray[j++] = stats[i].sharedDirty; 2720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 2730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 2740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2773025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object) 2783025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn{ 2793025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object); 2803025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn} 2813025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn 282b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackbornstatic jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid) 283b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn{ 284b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn char line[1024]; 285b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn jlong pss = 0; 286b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn unsigned temp; 287b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 288b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn char tmp[128]; 289b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn FILE *fp; 290b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 291b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn sprintf(tmp, "/proc/%d/smaps", pid); 292b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn fp = fopen(tmp, "r"); 293b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn if (fp == 0) return 0; 294b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 295b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn while (true) { 296b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn if (fgets(line, 1024, fp) == 0) { 297b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn break; 298b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn } 299b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 300b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn if (sscanf(line, "Pss: %d kB", &temp) == 1) { 301b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn pss += temp; 302b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn } 303b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn } 304b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 305b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn fclose(fp); 306b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 307b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn return pss; 308b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn} 309b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 310b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackbornstatic jlong android_os_Debug_getPss(JNIEnv *env, jobject clazz) 311b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn{ 312b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn return android_os_Debug_getPssPid(env, clazz, getpid()); 313b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn} 314b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint read_binder_stat(const char* stat) 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FILE* fp = fopen(BINDER_STATS, "r"); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fp == NULL) { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char line[1024]; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char compare[128]; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = snprintf(compare, 128, "proc %d", getpid()); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // loop until we have the block that represents this process 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fgets(line, 1024, fp) == 0) { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (strncmp(compare, line, len)); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now that we have this process, read until we find the stat that we are looking for 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len = snprintf(compare, 128, " %s: ", stat); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fgets(line, 1024, fp) == 0) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (strncmp(compare, line, len)); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we have the line, now increment the line ptr to the value 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* ptr = line + len; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return atoi(ptr); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_Debug_getBinderSentTransactions(JNIEnv *env, jobject clazz) 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return read_binder_stat("bcTRANSACTION"); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_getBinderReceivedTransactions(JNIEnv *env, jobject clazz) 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return read_binder_stat("brTRANSACTION"); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// these are implemented in android_util_Binder.cpp 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 36406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* pulled out of bionic */ 36506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, 36606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); 36706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void free_malloc_leak_info(uint8_t* info); 36806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define SIZE_FLAG_ZYGOTE_CHILD (1<<31) 36906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define BACKTRACE_SIZE 32 37006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 37106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* 37206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * This is a qsort() callback. 37306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 37406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * See dumpNativeHeap() for comments about the data format and sort order. 37506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */ 37606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic int compareHeapRecords(const void* vrec1, const void* vrec2) 37706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{ 37806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden const size_t* rec1 = (const size_t*) vrec1; 37906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden const size_t* rec2 = (const size_t*) vrec2; 38006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t size1 = *rec1; 38106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t size2 = *rec2; 38206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 38306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (size1 < size2) { 38406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return 1; 38506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } else if (size1 > size2) { 38606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return -1; 38706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 38806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 38906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t* bt1 = (intptr_t*)(rec1 + 2); 39006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t* bt2 = (intptr_t*)(rec2 + 2); 39106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden for (size_t idx = 0; idx < BACKTRACE_SIZE; idx++) { 39206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t addr1 = bt1[idx]; 39306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t addr2 = bt2[idx]; 39406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (addr1 == addr2) { 39506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (addr1 == 0) 39606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden break; 39706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden continue; 39806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 39906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (addr1 < addr2) { 40006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return -1; 40106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } else if (addr1 > addr2) { 40206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return 1; 40306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 40406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 40506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 40606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return 0; 40706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden} 40806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 40906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* 41006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The get_malloc_leak_info() call returns an array of structs that 41106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * look like this: 41206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 41306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * size_t size 41406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * size_t allocations 41506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * intptr_t backtrace[32] 41606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 41706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * "size" is the size of the allocation, "backtrace" is a fixed-size 41806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * array of function pointers, and "allocations" is the number of 41906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * allocations with the exact same size and backtrace. 42006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * 42106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The entries are sorted by descending total size (i.e. size*allocations) 42206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * then allocation count. For best results with "diff" we'd like to sort 42306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * primarily by individual size then stack trace. Since the entries are 42406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * fixed-size, and we're allowed (by the current implementation) to mangle 42506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * them, we can do this in place. 42606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */ 42706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void dumpNativeHeap(FILE* fp) 42806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{ 42906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden uint8_t* info = NULL; 43006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t overallSize, infoSize, totalMemory, backtraceSize; 43106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 43206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, 43306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden &backtraceSize); 43406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (info == NULL) { 43506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Native heap dump not available. To enable, run these" 43606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden " commands (requires root):\n"); 43706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "$ adb shell setprop libc.debug.malloc 1\n"); 43806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "$ adb shell stop\n"); 43906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "$ adb shell start\n"); 44006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 44106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 44206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden assert(infoSize != 0); 44306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden assert(overallSize % infoSize == 0); 44406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 44506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Android Native Heap Dump v1.0\n\n"); 44606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 44706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t recordCount = overallSize / infoSize; 44806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Total memory: %zu\n", totalMemory); 44906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "Allocation records: %zd\n", recordCount); 45006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (backtraceSize != BACKTRACE_SIZE) { 45106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n", 45206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden backtraceSize, BACKTRACE_SIZE); 45306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 45406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "\n"); 45506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 45606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden /* re-sort the entries */ 45706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden qsort(info, recordCount, infoSize, compareHeapRecords); 45806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 45906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden /* dump the entries to the file */ 46006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden const uint8_t* ptr = info; 46106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden for (size_t idx = 0; idx < recordCount; idx++) { 46206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t size = *(size_t*) ptr; 46306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size_t allocations = *(size_t*) (ptr + sizeof(size_t)); 46406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden intptr_t* backtrace = (intptr_t*) (ptr + sizeof(size_t) * 2); 46506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 46606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "z %d sz %8zu num %4zu bt", 46706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden (size & SIZE_FLAG_ZYGOTE_CHILD) != 0, 46806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden size & ~SIZE_FLAG_ZYGOTE_CHILD, 46906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden allocations); 47006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden for (size_t bt = 0; bt < backtraceSize; bt++) { 47106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (backtrace[bt] == 0) { 47206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden break; 47306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } else { 47406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, " %08x", backtrace[bt]); 47506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 47606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 47706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fprintf(fp, "\n"); 47806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 47906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden ptr += infoSize; 48006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 48106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 48206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden free_malloc_leak_info(info); 483393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom 484393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fprintf(fp, "MAPS\n"); 485393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom const char* maps = "/proc/self/maps"; 486393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom FILE* in = fopen(maps, "r"); 487393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom if (in == NULL) { 488393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fprintf(fp, "Could not open %s\n", maps); 489393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom return; 490393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom } 491393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom char buf[BUFSIZ]; 492393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) { 493393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fwrite(buf, sizeof(char), n, fp); 494393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom } 495393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fclose(in); 496393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom 497393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom fprintf(fp, "END\n"); 49806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden} 49906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 50006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* 50106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * Dump the native heap, writing human-readable output to the specified 50206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * file descriptor. 50306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */ 50406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz, 50506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jobject fileDescriptor) 50606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{ 50706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (fileDescriptor == NULL) { 50806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowNullPointerException(env, NULL); 50906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 51006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 51106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor); 51206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (origFd < 0) { 51306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowRuntimeException(env, "Invalid file descriptor"); 51406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 51506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 51606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 51706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden /* dup() the descriptor so we don't close the original with fclose() */ 51806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden int fd = dup(origFd); 51906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (fd < 0) { 52006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGW("dup(%d) failed: %s\n", origFd, strerror(errno)); 52106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowRuntimeException(env, "dup() failed"); 52206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 52306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 52406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 52506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden FILE* fp = fdopen(fd, "w"); 52606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden if (fp == NULL) { 52706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGW("fdopen(%d) failed: %s\n", fd, strerror(errno)); 52806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden close(fd); 52906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden jniThrowRuntimeException(env, "fdopen() failed"); 53006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden return; 53106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden } 53206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 53306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGD("Native heap dump starting...\n"); 53406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden dumpNativeHeap(fp); 53506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden LOGD("Native heap dump complete.\n"); 53606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 53706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden fclose(fp); 53806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden} 53906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 54006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration. 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = { 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getNativeHeapSize", "()J", 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getNativeHeapSize }, 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getNativeHeapAllocatedSize", "()J", 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getNativeHeapAllocatedSize }, 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getNativeHeapFreeSize", "()J", 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getNativeHeapFreeSize }, 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getMemoryInfo", "(Landroid/os/Debug$MemoryInfo;)V", 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getDirtyPages }, 5543025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn { "getMemoryInfo", "(ILandroid/os/Debug$MemoryInfo;)V", 5553025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn (void*) android_os_Debug_getDirtyPagesPid }, 556b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn { "getPss", "()J", 557b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn (void*) android_os_Debug_getPss }, 558b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn { "getPss", "(I)J", 559b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn (void*) android_os_Debug_getPssPid }, 56006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden { "dumpNativeHeap", "(Ljava/io/FileDescriptor;)V", 56106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden (void*) android_os_Debug_dumpNativeHeap }, 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderSentTransactions", "()I", 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_Debug_getBinderSentTransactions }, 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderReceivedTransactions", "()I", 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) android_os_getBinderReceivedTransactions }, 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderLocalObjectCount", "()I", 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_Debug_getLocalObjectCount }, 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderProxyObjectCount", "()I", 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_Debug_getProxyObjectCount }, 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "getBinderDeathObjectCount", "()I", 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_Debug_getDeathObjectCount }, 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_Debug(JNIEnv *env) 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz = env->FindClass("android/os/Debug$MemoryInfo"); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn for (int i=0; i<_NUM_CORE_HEAP; i++) { 5790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stat_fields[i].pss_field = 5800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->GetFieldID(clazz, stat_field_names[i].pss_name, "I"); 5810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stat_fields[i].privateDirty_field = 5820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I"); 5830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn stat_fields[i].sharedDirty_field = 5840e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I"); 5850e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn } 5860e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 5870e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn otherStats_field = env->GetFieldID(clazz, "otherStats", "[I"); 5880e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods)); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 59206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}; // namespace android 593