android_os_Debug.cpp revision 393b84c137fe52f42205cef7e63b7a04b4bfd789
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>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <malloc.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID dalvikPss_field;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID dalvikPrivateDirty_field;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID dalvikSharedDirty_field;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativePss_field;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativePrivateDirty_field;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID nativeSharedDirty_field;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID otherPss_field;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID otherPrivateDirty_field;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID otherSharedDirty_field;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct stats_t {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int dalvikPss;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int dalvikPrivateDirty;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int dalvikSharedDirty;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int nativePss;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int nativePrivateDirty;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int nativeSharedDirty;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int otherPss;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int otherPrivateDirty;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int otherSharedDirty;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BINDER_STATS "/proc/binder/stats"
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz)
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.usmblks;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz)
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.uordblks;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.fordblks;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void read_mapinfo(FILE *fp, stats_t* stats)
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char line[1024];
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int len;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool skip, done = false;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned start = 0, size = 0, resident = 0, pss = 0;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned shared_clean = 0, shared_dirty = 0;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned private_clean = 0, private_dirty = 0;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned referenced = 0;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned temp;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int isNativeHeap;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int isDalvikHeap;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int isSqliteHeap;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if(fgets(line, 1024, fp) == 0) return;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (!done) {
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        isNativeHeap = 0;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        isDalvikHeap = 0;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        isSqliteHeap = 0;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        skip = false;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len = strlen(line);
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len < 1) return;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        line[--len] = 0;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* ignore guard pages */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len > 18 && line[17] == '-') skip = true;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        start = strtoul(line, 0, 16);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strstr(line, "[heap]")) {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            isNativeHeap = 1;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strstr(line, "/dalvik-LinearAlloc")) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            isDalvikHeap = 1;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strstr(line, "/mspace/dalvik-heap")) {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            isDalvikHeap = 1;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strstr(line, "/dalvik-heap-bitmap/")) {
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            isDalvikHeap = 1;
135bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba        } else if (strstr(line, "/data/dalvik-cache/")) {
136bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba            isDalvikHeap = 1;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (strstr(line, "/tmp/sqlite-heap")) {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            isSqliteHeap = 1;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //    isSqliteHeap, line);
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (true) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fgets(line, 1024, fp) == 0) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                done = true;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sscanf(line, "Size: %d kB", &temp) == 1) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size = temp;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Rss: %d kB", &temp) == 1) {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                resident = temp;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Pss: %d kB", &temp) == 1) {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pss = temp;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                shared_clean = temp;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                shared_dirty = temp;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                private_clean = temp;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                private_dirty = temp;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (sscanf(line, "Referenced: %d kB", &temp) == 1) {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                referenced = temp;
166bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba            } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // looks like a new mapping
168bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba                // example: "10000000-10001000 ---p 10000000 00:00 0"
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!skip) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isNativeHeap) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->nativePss += pss;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->nativePrivateDirty += private_dirty;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->nativeSharedDirty += shared_dirty;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (isDalvikHeap) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->dalvikPss += pss;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->dalvikPrivateDirty += private_dirty;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->dalvikSharedDirty += shared_dirty;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ( isSqliteHeap) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // ignore
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                stats->otherPss += pss;
186bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba                stats->otherPrivateDirty += private_dirty;
187bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba                stats->otherSharedDirty += shared_dirty;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void load_maps(int pid, stats_t* stats)
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char tmp[128];
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE *fp;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sprintf(tmp, "/proc/%d/smaps", pid);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fp = fopen(tmp, "r");
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == 0) return;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    read_mapinfo(fp, stats);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fclose(fp);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2063025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
2073025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn        jint pid, jobject object)
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    stats_t stats;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(&stats, 0, sizeof(stats_t));
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2123025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    load_maps(pid, &stats);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, dalvikPss_field, stats.dalvikPss);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, dalvikSharedDirty_field, stats.dalvikSharedDirty);
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, nativePss_field, stats.nativePss);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, nativePrivateDirty_field, stats.nativePrivateDirty);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, nativeSharedDirty_field, stats.nativeSharedDirty);
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, otherPss_field, stats.otherPss);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, otherPrivateDirty_field, stats.otherPrivateDirty);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2273025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
2283025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn{
2293025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
2303025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn}
2313025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint read_binder_stat(const char* stat)
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE* fp = fopen(BINDER_STATS, "r");
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == NULL) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char line[1024];
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char compare[128];
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int len = snprintf(compare, 128, "proc %d", getpid());
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // loop until we have the block that represents this process
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fgets(line, 1024, fp) == 0) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (strncmp(compare, line, len));
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // now that we have this process, read until we find the stat that we are looking for
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = snprintf(compare, 128, "  %s: ", stat);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fgets(line, 1024, fp) == 0) {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (strncmp(compare, line, len));
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // we have the line, now increment the line ptr to the value
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char* ptr = line + len;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return atoi(ptr);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_Debug_getBinderSentTransactions(JNIEnv *env, jobject clazz)
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read_binder_stat("bcTRANSACTION");
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_getBinderReceivedTransactions(JNIEnv *env, jobject clazz)
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read_binder_stat("brTRANSACTION");
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// these are implemented in android_util_Binder.cpp
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz);
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
28106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#ifdef HAVE_ANDROID_OS
28206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* pulled out of bionic */
28306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
28406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
28506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void free_malloc_leak_info(uint8_t* info);
28606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define SIZE_FLAG_ZYGOTE_CHILD  (1<<31)
28706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define BACKTRACE_SIZE          32
28806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
28906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
29006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * This is a qsort() callback.
29106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
29206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * See dumpNativeHeap() for comments about the data format and sort order.
29306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
29406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic int compareHeapRecords(const void* vrec1, const void* vrec2)
29506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
29606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const size_t* rec1 = (const size_t*) vrec1;
29706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const size_t* rec2 = (const size_t*) vrec2;
29806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t size1 = *rec1;
29906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t size2 = *rec2;
30006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
30106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (size1 < size2) {
30206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return 1;
30306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    } else if (size1 > size2) {
30406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return -1;
30506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
30606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
30706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    intptr_t* bt1 = (intptr_t*)(rec1 + 2);
30806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    intptr_t* bt2 = (intptr_t*)(rec2 + 2);
30906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    for (size_t idx = 0; idx < BACKTRACE_SIZE; idx++) {
31006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t addr1 = bt1[idx];
31106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t addr2 = bt2[idx];
31206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (addr1 == addr2) {
31306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (addr1 == 0)
31406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                break;
31506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            continue;
31606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
31706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (addr1 < addr2) {
31806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return -1;
31906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        } else if (addr1 > addr2) {
32006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return 1;
32106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
32206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
32306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
32406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    return 0;
32506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
32606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
32706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
32806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The get_malloc_leak_info() call returns an array of structs that
32906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * look like this:
33006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
33106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   size_t size
33206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   size_t allocations
33306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   intptr_t backtrace[32]
33406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
33506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * "size" is the size of the allocation, "backtrace" is a fixed-size
33606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * array of function pointers, and "allocations" is the number of
33706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * allocations with the exact same size and backtrace.
33806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
33906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The entries are sorted by descending total size (i.e. size*allocations)
34006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * then allocation count.  For best results with "diff" we'd like to sort
34106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * primarily by individual size then stack trace.  Since the entries are
34206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * fixed-size, and we're allowed (by the current implementation) to mangle
34306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * them, we can do this in place.
34406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
34506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void dumpNativeHeap(FILE* fp)
34606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
34706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    uint8_t* info = NULL;
34806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t overallSize, infoSize, totalMemory, backtraceSize;
34906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
35006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory,
35106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        &backtraceSize);
35206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (info == NULL) {
35306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "Native heap dump not available. To enable, run these"
35406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    " commands (requires root):\n");
35506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell setprop libc.debug.malloc 1\n");
35606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell stop\n");
35706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell start\n");
35806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
35906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
36006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    assert(infoSize != 0);
36106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    assert(overallSize % infoSize == 0);
36206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
36306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Android Native Heap Dump v1.0\n\n");
36406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
36506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t recordCount = overallSize / infoSize;
36606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Total memory: %zu\n", totalMemory);
36706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Allocation records: %zd\n", recordCount);
36806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (backtraceSize != BACKTRACE_SIZE) {
36906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n",
37006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            backtraceSize, BACKTRACE_SIZE);
37106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
37206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "\n");
37306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
37406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* re-sort the entries */
37506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    qsort(info, recordCount, infoSize, compareHeapRecords);
37606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
37706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* dump the entries to the file */
37806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const uint8_t* ptr = info;
37906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    for (size_t idx = 0; idx < recordCount; idx++) {
38006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        size_t size = *(size_t*) ptr;
38106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        size_t allocations = *(size_t*) (ptr + sizeof(size_t));
38206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t* backtrace = (intptr_t*) (ptr + sizeof(size_t) * 2);
38306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
38406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "z %d  sz %8zu  num %4zu  bt",
38506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                (size & SIZE_FLAG_ZYGOTE_CHILD) != 0,
38606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                size & ~SIZE_FLAG_ZYGOTE_CHILD,
38706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                allocations);
38806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        for (size_t bt = 0; bt < backtraceSize; bt++) {
38906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (backtrace[bt] == 0) {
39006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                break;
39106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            } else {
39206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                fprintf(fp, " %08x", backtrace[bt]);
39306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
39406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
39506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "\n");
39606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
39706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        ptr += infoSize;
39806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
39906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
40006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    free_malloc_leak_info(info);
401393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
402393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fprintf(fp, "MAPS\n");
403393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    const char* maps = "/proc/self/maps";
404393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    FILE* in = fopen(maps, "r");
405393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    if (in == NULL) {
406393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        fprintf(fp, "Could not open %s\n", maps);
407393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        return;
408393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    }
409393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    char buf[BUFSIZ];
410393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) {
411393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        fwrite(buf, sizeof(char), n, fp);
412393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    }
413393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fclose(in);
414393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
415393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fprintf(fp, "END\n");
41606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
41706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#endif /*HAVE_ANDROID_OS*/
41806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
41906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
42006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * Dump the native heap, writing human-readable output to the specified
42106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * file descriptor.
42206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
42306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
42406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    jobject fileDescriptor)
42506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
42606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fileDescriptor == NULL) {
42706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowNullPointerException(env, NULL);
42806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
42906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
43006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
43106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (origFd < 0) {
43206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "Invalid file descriptor");
43306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
43406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
43506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
43606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* dup() the descriptor so we don't close the original with fclose() */
43706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    int fd = dup(origFd);
43806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fd < 0) {
43906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        LOGW("dup(%d) failed: %s\n", origFd, strerror(errno));
44006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "dup() failed");
44106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
44206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
44306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
44406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    FILE* fp = fdopen(fd, "w");
44506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fp == NULL) {
44606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        LOGW("fdopen(%d) failed: %s\n", fd, strerror(errno));
44706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        close(fd);
44806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "fdopen() failed");
44906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
45006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
45106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
45206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#ifdef HAVE_ANDROID_OS
45306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    LOGD("Native heap dump starting...\n");
45406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    dumpNativeHeap(fp);
45506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    LOGD("Native heap dump complete.\n");
45606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#else
45706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Native heap dump not available on this platform\n");
45806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#endif
45906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
46006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fclose(fp);
46106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
46206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
46306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration.
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapSize",      "()J",
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapSize },
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapAllocatedSize", "()J",
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapAllocatedSize },
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapFreeSize",  "()J",
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapFreeSize },
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getMemoryInfo",          "(Landroid/os/Debug$MemoryInfo;)V",
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getDirtyPages },
4773025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    { "getMemoryInfo",          "(ILandroid/os/Debug$MemoryInfo;)V",
4783025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            (void*) android_os_Debug_getDirtyPagesPid },
47906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    { "dumpNativeHeap",         "(Ljava/io/FileDescriptor;)V",
48006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            (void*) android_os_Debug_dumpNativeHeap },
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderSentTransactions", "()I",
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getBinderSentTransactions },
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderReceivedTransactions", "()I",
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_getBinderReceivedTransactions },
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderLocalObjectCount", "()I",
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getLocalObjectCount },
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderProxyObjectCount", "()I",
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getProxyObjectCount },
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderDeathObjectCount", "()I",
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getDeathObjectCount },
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_Debug(JNIEnv *env)
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dalvikPss_field = env->GetFieldID(clazz, "dalvikPss", "I");
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dalvikPrivateDirty_field = env->GetFieldID(clazz, "dalvikPrivateDirty", "I");
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dalvikSharedDirty_field = env->GetFieldID(clazz, "dalvikSharedDirty", "I");
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    nativePss_field = env->GetFieldID(clazz, "nativePss", "I");
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    nativePrivateDirty_field = env->GetFieldID(clazz, "nativePrivateDirty", "I");
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    nativeSharedDirty_field = env->GetFieldID(clazz, "nativeSharedDirty", "I");
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    otherPss_field = env->GetFieldID(clazz, "otherPss", "I");
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    otherPrivateDirty_field = env->GetFieldID(clazz, "otherPrivateDirty", "I");
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    otherSharedDirty_field = env->GetFieldID(clazz, "otherSharedDirty", "I");
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
51206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}; // namespace android
513