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"
20f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include <utils/String8.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h"
22f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include "cutils/debugger.h"
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include <fcntl.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <time.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h>
3106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <errno.h>
3206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <assert.h>
330e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn#include <ctype.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <malloc.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornenum {
430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_UNKNOWN,
440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_DALVIK,
450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_NATIVE,
467c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    HEAP_STACK,
470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_CURSOR,
480e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_ASHMEM,
490e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_UNKNOWN_DEV,
500e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_SO,
510e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_JAR,
520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_APK,
530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_TTF,
540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_DEX,
550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_UNKNOWN_MAP,
560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    _NUM_HEAP,
580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    _NUM_CORE_HEAP = HEAP_NATIVE+1
590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
610e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstruct stat_fields {
620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jfieldID pss_field;
630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jfieldID privateDirty_field;
640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jfieldID sharedDirty_field;
650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstruct stat_field_names {
680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const char* pss_name;
690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const char* privateDirty_name;
700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const char* sharedDirty_name;
710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic stat_fields stat_fields[_NUM_CORE_HEAP];
740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    { "otherPss", "otherPrivateDirty", "otherSharedDirty" },
770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    { "dalvikPss", "dalvikPrivateDirty", "dalvikSharedDirty" },
780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    { "nativePss", "nativePrivateDirty", "nativeSharedDirty" }
790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne HackbornjfieldID otherStats_field;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct stats_t {
840e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int pss;
850e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int privateDirty;
860e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int sharedDirty;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BINDER_STATS "/proc/binder/stats"
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz)
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.usmblks;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz)
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.uordblks;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1137c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers#ifdef HAVE_MALLOC_H
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.fordblks;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void read_mapinfo(FILE *fp, stats_t* stats)
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char line[1024];
1240e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int len, nameLen;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool skip, done = false;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    unsigned size = 0, resident = 0, pss = 0;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned shared_clean = 0, shared_dirty = 0;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned private_clean = 0, private_dirty = 0;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned referenced = 0;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned temp;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1330e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    unsigned long int start;
1340e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    unsigned long int end = 0;
1350e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    unsigned long int prevEnd = 0;
1360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    char* name;
1370e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int name_pos;
1380e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1390e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int whichHeap = HEAP_UNKNOWN;
1400e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int prevHeap = HEAP_UNKNOWN;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if(fgets(line, sizeof(line), fp) == 0) return;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (!done) {
1450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        prevHeap = whichHeap;
1460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        prevEnd = end;
1470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        whichHeap = HEAP_UNKNOWN;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        skip = false;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len = strlen(line);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len < 1) return;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        line[--len] = 0;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
1550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            skip = true;
1560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        } else {
1570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            while (isspace(line[name_pos])) {
1580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                name_pos += 1;
1590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            }
1600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            name = line + name_pos;
1610e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            nameLen = strlen(name);
1620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
163afc10e174d73363185f42cb67ec429a64549f2c7Ian Rogers            if ((strstr(name, "[heap]") == name) ||
164afc10e174d73363185f42cb67ec429a64549f2c7Ian Rogers                (strstr(name, "/dev/ashmem/libc malloc") == name)) {
1650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_NATIVE;
1660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (strstr(name, "/dev/ashmem/dalvik-") == name) {
1670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_DALVIK;
1687c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            } else if (strstr(name, "[stack") == name) {
1697c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                whichHeap = HEAP_STACK;
1700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (strstr(name, "/dev/ashmem/CursorWindow") == name) {
1710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_CURSOR;
1720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (strstr(name, "/dev/ashmem/") == name) {
1730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_ASHMEM;
1740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (strstr(name, "/dev/") == name) {
1750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_UNKNOWN_DEV;
1760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
1770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_SO;
1780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) {
1790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_JAR;
1800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) {
1810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_APK;
1820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
1830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_TTF;
1849f8589c31f8910a9c3c33a81675822da9f0cf2dfIan Rogers            } else if ((nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) ||
1859f8589c31f8910a9c3c33a81675822da9f0cf2dfIan Rogers                       (nameLen > 5 && strcmp(name+nameLen-5, ".odex") == 0)) {
1860e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_DEX;
1870e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 0) {
1880e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_UNKNOWN_MAP;
1890e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (start == prevEnd && prevHeap == HEAP_SO) {
1900e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                // bss section of a shared library.
1910e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_SO;
1920e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1956215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        //ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //    isSqliteHeap, line);
1977c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (true) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fgets(line, 1024, fp) == 0) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                done = true;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sscanf(line, "Size: %d kB", &temp) == 1) {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size = temp;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Rss: %d kB", &temp) == 1) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                resident = temp;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Pss: %d kB", &temp) == 1) {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pss = temp;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                shared_clean = temp;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                shared_dirty = temp;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                private_clean = temp;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                private_dirty = temp;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Referenced: %d kB", &temp) == 1) {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                referenced = temp;
220bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba            } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // looks like a new mapping
222bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba                // example: "10000000-10001000 ---p 10000000 00:00 0"
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!skip) {
2280e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            stats[whichHeap].pss += pss;
2290e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            stats[whichHeap].privateDirty += private_dirty;
2300e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            stats[whichHeap].sharedDirty += shared_dirty;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void load_maps(int pid, stats_t* stats)
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char tmp[128];
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE *fp;
2397c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sprintf(tmp, "/proc/%d/smaps", pid);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fp = fopen(tmp, "r");
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == 0) return;
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    read_mapinfo(fp, stats);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fclose(fp);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2483025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
2493025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn        jint pid, jobject object)
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2510e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    stats_t stats[_NUM_HEAP];
2520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    memset(&stats, 0, sizeof(stats));
2537c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
2540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    load_maps(pid, stats);
2550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
2570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stats[HEAP_UNKNOWN].pss += stats[i].pss;
2580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty;
2590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
2600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=0; i<_NUM_CORE_HEAP; i++) {
2630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss);
2640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
2650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
2660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
2677c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
2680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
2697c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
2700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
2710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if (otherArray == NULL) {
2720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        return;
2730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
2740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int j=0;
2760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
2770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        otherArray[j++] = stats[i].pss;
2780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        otherArray[j++] = stats[i].privateDirty;
2790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        otherArray[j++] = stats[i].sharedDirty;
2800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
2810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2853025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
2863025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn{
2873025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
2883025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn}
2893025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn
290b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackbornstatic jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid)
291b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn{
292b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    char line[1024];
293b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    jlong pss = 0;
294b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    unsigned temp;
295b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
296b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    char tmp[128];
297b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    FILE *fp;
298b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
299b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    sprintf(tmp, "/proc/%d/smaps", pid);
300b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    fp = fopen(tmp, "r");
301b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    if (fp == 0) return 0;
302b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
303b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    while (true) {
304b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        if (fgets(line, 1024, fp) == 0) {
305b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            break;
306b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
307b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
308b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        if (sscanf(line, "Pss: %d kB", &temp) == 1) {
309b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            pss += temp;
310b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
311b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    }
312b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
313b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    fclose(fp);
314b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
315b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    return pss;
316b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn}
317b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
318b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackbornstatic jlong android_os_Debug_getPss(JNIEnv *env, jobject clazz)
319b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn{
320b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    return android_os_Debug_getPssPid(env, clazz, getpid());
321b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn}
322b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint read_binder_stat(const char* stat)
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE* fp = fopen(BINDER_STATS, "r");
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == NULL) {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char line[1024];
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char compare[128];
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int len = snprintf(compare, 128, "proc %d", getpid());
3347c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // loop until we have the block that represents this process
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fgets(line, 1024, fp) == 0) {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (strncmp(compare, line, len));
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3427c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    // now that we have this process, read until we find the stat that we are looking for
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = snprintf(compare, 128, "  %s: ", stat);
3447c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fgets(line, 1024, fp) == 0) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (strncmp(compare, line, len));
3507c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // we have the line, now increment the line ptr to the value
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char* ptr = line + len;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return atoi(ptr);
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_Debug_getBinderSentTransactions(JNIEnv *env, jobject clazz)
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read_binder_stat("bcTRANSACTION");
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_getBinderReceivedTransactions(JNIEnv *env, jobject clazz)
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read_binder_stat("brTRANSACTION");
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// these are implemented in android_util_Binder.cpp
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz);
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
37206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* pulled out of bionic */
37306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
37406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
37506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void free_malloc_leak_info(uint8_t* info);
37606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define SIZE_FLAG_ZYGOTE_CHILD  (1<<31)
37706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define BACKTRACE_SIZE          32
37806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
37906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
38006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * This is a qsort() callback.
38106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
38206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * See dumpNativeHeap() for comments about the data format and sort order.
38306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
38406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic int compareHeapRecords(const void* vrec1, const void* vrec2)
38506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
38606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const size_t* rec1 = (const size_t*) vrec1;
38706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const size_t* rec2 = (const size_t*) vrec2;
38806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t size1 = *rec1;
38906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t size2 = *rec2;
39006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
39106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (size1 < size2) {
39206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return 1;
39306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    } else if (size1 > size2) {
39406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return -1;
39506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
39606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
39706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    intptr_t* bt1 = (intptr_t*)(rec1 + 2);
39806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    intptr_t* bt2 = (intptr_t*)(rec2 + 2);
39906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    for (size_t idx = 0; idx < BACKTRACE_SIZE; idx++) {
40006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t addr1 = bt1[idx];
40106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t addr2 = bt2[idx];
40206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (addr1 == addr2) {
40306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (addr1 == 0)
40406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                break;
40506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            continue;
40606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
40706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (addr1 < addr2) {
40806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return -1;
40906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        } else if (addr1 > addr2) {
41006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return 1;
41106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
41206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
41306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
41406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    return 0;
41506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
41606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
41706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
41806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The get_malloc_leak_info() call returns an array of structs that
41906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * look like this:
42006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
42106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   size_t size
42206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   size_t allocations
42306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   intptr_t backtrace[32]
42406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
42506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * "size" is the size of the allocation, "backtrace" is a fixed-size
42606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * array of function pointers, and "allocations" is the number of
42706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * allocations with the exact same size and backtrace.
42806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
42906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The entries are sorted by descending total size (i.e. size*allocations)
43006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * then allocation count.  For best results with "diff" we'd like to sort
43106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * primarily by individual size then stack trace.  Since the entries are
43206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * fixed-size, and we're allowed (by the current implementation) to mangle
43306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * them, we can do this in place.
43406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
43506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void dumpNativeHeap(FILE* fp)
43606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
43706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    uint8_t* info = NULL;
43806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t overallSize, infoSize, totalMemory, backtraceSize;
43906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
44006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory,
44106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        &backtraceSize);
44206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (info == NULL) {
44306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "Native heap dump not available. To enable, run these"
44406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    " commands (requires root):\n");
44506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell setprop libc.debug.malloc 1\n");
44606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell stop\n");
44706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell start\n");
44806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
44906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
45006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    assert(infoSize != 0);
45106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    assert(overallSize % infoSize == 0);
45206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
45306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Android Native Heap Dump v1.0\n\n");
45406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
45506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t recordCount = overallSize / infoSize;
45606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Total memory: %zu\n", totalMemory);
45706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Allocation records: %zd\n", recordCount);
45806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (backtraceSize != BACKTRACE_SIZE) {
45906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n",
46006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            backtraceSize, BACKTRACE_SIZE);
46106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
46206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "\n");
46306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
46406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* re-sort the entries */
46506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    qsort(info, recordCount, infoSize, compareHeapRecords);
46606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
46706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* dump the entries to the file */
46806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const uint8_t* ptr = info;
46906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    for (size_t idx = 0; idx < recordCount; idx++) {
47006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        size_t size = *(size_t*) ptr;
47106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        size_t allocations = *(size_t*) (ptr + sizeof(size_t));
47206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t* backtrace = (intptr_t*) (ptr + sizeof(size_t) * 2);
47306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
47406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "z %d  sz %8zu  num %4zu  bt",
47506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                (size & SIZE_FLAG_ZYGOTE_CHILD) != 0,
47606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                size & ~SIZE_FLAG_ZYGOTE_CHILD,
47706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                allocations);
47806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        for (size_t bt = 0; bt < backtraceSize; bt++) {
47906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (backtrace[bt] == 0) {
48006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                break;
48106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            } else {
48206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                fprintf(fp, " %08x", backtrace[bt]);
48306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
48406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
48506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "\n");
48606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
48706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        ptr += infoSize;
48806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
48906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
49006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    free_malloc_leak_info(info);
491393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
492393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fprintf(fp, "MAPS\n");
493393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    const char* maps = "/proc/self/maps";
494393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    FILE* in = fopen(maps, "r");
495393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    if (in == NULL) {
496393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        fprintf(fp, "Could not open %s\n", maps);
497393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        return;
498393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    }
499393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    char buf[BUFSIZ];
500393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) {
501393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        fwrite(buf, sizeof(char), n, fp);
502393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    }
503393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fclose(in);
504393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
505393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fprintf(fp, "END\n");
50606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
50706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
50806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
50906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * Dump the native heap, writing human-readable output to the specified
51006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * file descriptor.
51106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
51206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
51306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    jobject fileDescriptor)
51406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
51506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fileDescriptor == NULL) {
5167c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        jniThrowNullPointerException(env, "fd == null");
51706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
51806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
51906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
52006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (origFd < 0) {
52106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "Invalid file descriptor");
52206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
52306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
52406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
52506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* dup() the descriptor so we don't close the original with fclose() */
52606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    int fd = dup(origFd);
52706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fd < 0) {
5288564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("dup(%d) failed: %s\n", origFd, strerror(errno));
52906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "dup() failed");
53006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
53106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
53206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
53306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    FILE* fp = fdopen(fd, "w");
53406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fp == NULL) {
5358564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("fdopen(%d) failed: %s\n", fd, strerror(errno));
53606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        close(fd);
53706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "fdopen() failed");
53806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
53906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
54006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
5415baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("Native heap dump starting...\n");
54206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    dumpNativeHeap(fp);
5435baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("Native heap dump complete.\n");
54406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
54506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fclose(fp);
54606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
54706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
54806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
549f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackbornstatic void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject clazz,
550f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    jint pid, jstring fileName)
551f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn{
552f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (fileName == NULL) {
5537c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        jniThrowNullPointerException(env, "file == null");
554f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        return;
555f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
556f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    const jchar* str = env->GetStringCritical(fileName, 0);
557f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    String8 fileName8;
558f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (str) {
559f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        fileName8 = String8(str, env->GetStringLength(fileName));
560f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        env->ReleaseStringCritical(fileName, str);
561f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
562f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
563f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666);  /* -rw-rw-rw- */
564f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (fd < 0) {
565f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        fprintf(stderr, "Can't open %s: %s\n", fileName8.string(), strerror(errno));
566f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        return;
567f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
568f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
569f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (lseek(fd, 0, SEEK_END) < 0) {
570f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        fprintf(stderr, "lseek: %s\n", strerror(errno));
571f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    } else {
572f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        dump_backtrace_to_file(pid, fd);
573f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
574f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
575f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    close(fd);
576f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn}
577f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration.
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapSize",      "()J",
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapSize },
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapAllocatedSize", "()J",
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapAllocatedSize },
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapFreeSize",  "()J",
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapFreeSize },
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getMemoryInfo",          "(Landroid/os/Debug$MemoryInfo;)V",
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getDirtyPages },
5913025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    { "getMemoryInfo",          "(ILandroid/os/Debug$MemoryInfo;)V",
5923025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            (void*) android_os_Debug_getDirtyPagesPid },
593b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    { "getPss",                 "()J",
594b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            (void*) android_os_Debug_getPss },
595b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    { "getPss",                 "(I)J",
596b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            (void*) android_os_Debug_getPssPid },
59706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    { "dumpNativeHeap",         "(Ljava/io/FileDescriptor;)V",
59806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            (void*) android_os_Debug_dumpNativeHeap },
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderSentTransactions", "()I",
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getBinderSentTransactions },
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderReceivedTransactions", "()I",
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_getBinderReceivedTransactions },
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderLocalObjectCount", "()I",
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getLocalObjectCount },
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderProxyObjectCount", "()I",
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getProxyObjectCount },
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderDeathObjectCount", "()I",
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getDeathObjectCount },
609f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
610f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            (void*)android_os_Debug_dumpNativeBacktraceToFile },
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_Debug(JNIEnv *env)
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6177c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    // Sanity check the number of other statistics expected in Java matches here.
6187c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    jfieldID numOtherStats_field = env->GetStaticFieldID(clazz, "NUM_OTHER_STATS", "I");
6197c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    jint numOtherStats = env->GetStaticIntField(clazz, numOtherStats_field);
6207c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    int expectedNumOtherStats = _NUM_HEAP - _NUM_CORE_HEAP;
6217c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    if (numOtherStats != expectedNumOtherStats) {
6227c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
6237c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                             "android.os.Debug.Meminfo.NUM_OTHER_STATS=%d expected %d",
6247c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                             numOtherStats, expectedNumOtherStats);
6257c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        return JNI_ERR;
6267c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    }
6277c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
6287c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
6297c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
6300e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=0; i<_NUM_CORE_HEAP; i++) {
6310e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stat_fields[i].pss_field =
6320e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
6330e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stat_fields[i].privateDirty_field =
6340e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I");
6350e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stat_fields[i].sharedDirty_field =
6360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I");
6370e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
6380e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
64206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}; // namespace android
643