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"
235b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski#include <memtrack/memtrack.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2587eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include <cutils/log.h>
26f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include <fcntl.h>
27853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn#include <inttypes.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <time.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h>
3406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <errno.h>
3506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <assert.h>
360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn#include <ctype.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <malloc.h>
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornenum {
460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_UNKNOWN,
470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_DALVIK,
480e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_NATIVE,
49184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn
5064770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn    HEAP_DALVIK_OTHER,
517c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    HEAP_STACK,
520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_CURSOR,
530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_ASHMEM,
54184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn    HEAP_GL_DEV,
550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_UNKNOWN_DEV,
560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_SO,
570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_JAR,
580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_APK,
590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_TTF,
600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_DEX,
618884ef4fe80505bc6e41c167b67efbb93e43475dAnwar Ghuloum    HEAP_OAT,
6288887d0a53f866e61a7524b0edfc95e6dde57d72Anwar Ghuloum    HEAP_ART,
630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    HEAP_UNKNOWN_MAP,
645b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    HEAP_GRAPHICS,
655b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    HEAP_GL,
665b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    HEAP_OTHER_MEMTRACK,
6764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn
683c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    HEAP_DALVIK_NORMAL,
693c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    HEAP_DALVIK_LARGE,
703c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    HEAP_DALVIK_LINEARALLOC,
713c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    HEAP_DALVIK_ACCOUNTING,
723c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    HEAP_DALVIK_CODE_CACHE,
7325c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier    HEAP_DALVIK_ZYGOTE,
7425c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier    HEAP_DALVIK_NON_MOVING,
7525c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier    HEAP_DALVIK_INDIRECT_REFERENCE_TABLE,
760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    _NUM_HEAP,
785b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    _NUM_EXCLUSIVE_HEAP = HEAP_OTHER_MEMTRACK+1,
790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    _NUM_CORE_HEAP = HEAP_NATIVE+1
800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstruct stat_fields {
830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jfieldID pss_field;
843c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    jfieldID pssSwappable_field;
850e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jfieldID privateDirty_field;
860e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jfieldID sharedDirty_field;
873c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    jfieldID privateClean_field;
883a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum    jfieldID sharedClean_field;
898883ced18ac25199330843964634fdf70647a127Dianne Hackborn    jfieldID swappedOut_field;
900e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
910e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
920e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstruct stat_field_names {
930e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const char* pss_name;
943c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    const char* pssSwappable_name;
950e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const char* privateDirty_name;
960e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const char* sharedDirty_name;
973c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    const char* privateClean_name;
983a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum    const char* sharedClean_name;
998883ced18ac25199330843964634fdf70647a127Dianne Hackborn    const char* swappedOut_name;
1000e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
1010e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1020e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic stat_fields stat_fields[_NUM_CORE_HEAP];
1030e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1040e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
1058883ced18ac25199330843964634fdf70647a127Dianne Hackborn    { "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty",
1068883ced18ac25199330843964634fdf70647a127Dianne Hackborn        "otherPrivateClean", "otherSharedClean", "otherSwappedOut" },
1078883ced18ac25199330843964634fdf70647a127Dianne Hackborn    { "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty",
1088883ced18ac25199330843964634fdf70647a127Dianne Hackborn        "dalvikPrivateClean", "dalvikSharedClean", "dalvikSwappedOut" },
1098883ced18ac25199330843964634fdf70647a127Dianne Hackborn    { "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty",
1108883ced18ac25199330843964634fdf70647a127Dianne Hackborn        "nativePrivateClean", "nativeSharedClean", "nativeSwappedOut" }
1110e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn};
1120e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1130e3328fbdd3845b0e2bec364e951498eaee6b079Dianne HackbornjfieldID otherStats_field;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1155b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinskistatic bool memtrackLoaded;
1165b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct stats_t {
1180e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int pss;
1193c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    int swappablePss;
1200e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int privateDirty;
1210e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int sharedDirty;
1223c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    int privateClean;
1233a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum    int sharedClean;
1248883ced18ac25199330843964634fdf70647a127Dianne Hackborn    int swappedOut;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BINDER_STATS "/proc/binder/stats"
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz)
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.usmblks;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz)
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_MALLOC_H
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.uordblks;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1517c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers#ifdef HAVE_MALLOC_H
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct mallinfo info = mallinfo();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (jlong) info.fordblks;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1595b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski// Container used to retrieve graphics memory pss
1605b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinskistruct graphics_memory_pss
16137c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn{
1625b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    int graphics;
1635b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    int gl;
1645b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    int other;
1655b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski};
16637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
1675b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski/*
1685b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski * Uses libmemtrack to retrieve graphics memory that the process is using.
1695b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski * Any graphics memory reported in /proc/pid/smaps is not included here.
1705b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski */
171cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackbornstatic int read_memtrack_memory(struct memtrack_proc* p, int pid,
172cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn        struct graphics_memory_pss* graphics_mem)
1735b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski{
1745b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    int err = memtrack_proc_get(p, pid);
1755b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (err != 0) {
176cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn        ALOGW("failed to get memory consumption info: %d", err);
1775b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        return err;
17837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    }
17937c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
1805b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    ssize_t pss = memtrack_proc_graphics_pss(p);
1815b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (pss < 0) {
1820c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross        ALOGW("failed to get graphics pss: %zd", pss);
1835b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        return pss;
1845b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
1855b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    graphics_mem->graphics = pss / 1024;
18637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
1875b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    pss = memtrack_proc_gl_pss(p);
1885b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (pss < 0) {
1890c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross        ALOGW("failed to get gl pss: %zd", pss);
1905b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        return pss;
1915b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
1925b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    graphics_mem->gl = pss / 1024;
19337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
1945b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    pss = memtrack_proc_other_pss(p);
1955b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (pss < 0) {
1960c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross        ALOGW("failed to get other pss: %zd", pss);
1975b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        return pss;
1985b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
1995b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    graphics_mem->other = pss / 1024;
20037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
2015b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    return 0;
2025b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski}
20337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
2045b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski/*
2055b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski * Retrieves the graphics memory that is unaccounted for in /proc/pid/smaps.
2065b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski */
2075b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinskistatic int read_memtrack_memory(int pid, struct graphics_memory_pss* graphics_mem)
2085b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski{
2095b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (!memtrackLoaded) {
2105b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        return -1;
21137c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    }
21237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
2135b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    struct memtrack_proc* p = memtrack_proc_new();
2145b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (p == NULL) {
215cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn        ALOGW("failed to create memtrack_proc");
2165b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        return -1;
2175b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
21837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
2195b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    int err = read_memtrack_memory(p, pid, graphics_mem);
2205b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    memtrack_proc_destroy(p);
2215b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    return err;
22237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn}
22337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void read_mapinfo(FILE *fp, stats_t* stats)
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char line[1024];
2270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int len, nameLen;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool skip, done = false;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2303c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    unsigned size = 0, resident = 0, pss = 0, swappable_pss = 0;
2313c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    float sharing_proportion = 0.0;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned shared_clean = 0, shared_dirty = 0;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned private_clean = 0, private_dirty = 0;
2348883ced18ac25199330843964634fdf70647a127Dianne Hackborn    unsigned swapped_out = 0;
2353c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    bool is_swappable = false;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned referenced = 0;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned temp;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2390c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    uint64_t start;
2400c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    uint64_t end = 0;
2410c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    uint64_t prevEnd = 0;
2420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    char* name;
2430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int name_pos;
2440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int whichHeap = HEAP_UNKNOWN;
2463c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    int subHeap = HEAP_UNKNOWN;
2470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int prevHeap = HEAP_UNKNOWN;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2490e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if(fgets(line, sizeof(line), fp) == 0) return;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (!done) {
2520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        prevHeap = whichHeap;
2530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        prevEnd = end;
2540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        whichHeap = HEAP_UNKNOWN;
2553c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        subHeap = HEAP_UNKNOWN;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        skip = false;
2573c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        is_swappable = false;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        len = strlen(line);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len < 1) return;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        line[--len] = 0;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2630c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross        if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
2640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            skip = true;
2650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        } else {
2660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            while (isspace(line[name_pos])) {
2670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                name_pos += 1;
2680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            }
2690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            name = line + name_pos;
2700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            nameLen = strlen(name);
2710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
27264770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            if ((strstr(name, "[heap]") == name)) {
2730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_NATIVE;
27464770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            } else if (strncmp(name, "/dev/ashmem", 11) == 0) {
27564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                if (strncmp(name, "/dev/ashmem/dalvik-", 19) == 0) {
27664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    whichHeap = HEAP_DALVIK_OTHER;
27764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    if (strstr(name, "/dev/ashmem/dalvik-LinearAlloc") == name) {
27864770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                        subHeap = HEAP_DALVIK_LINEARALLOC;
279eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                    } else if ((strstr(name, "/dev/ashmem/dalvik-alloc space") == name) ||
28025c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                               (strstr(name, "/dev/ashmem/dalvik-main space") == name)) {
281eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                        // This is the regular Dalvik heap.
282eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                        whichHeap = HEAP_DALVIK;
283eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                        subHeap = HEAP_DALVIK_NORMAL;
284eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                    } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name) {
28564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                        whichHeap = HEAP_DALVIK;
28664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                        subHeap = HEAP_DALVIK_LARGE;
28725c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                    } else if (strstr(name, "/dev/ashmem/dalvik-non moving space") == name) {
28825c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                        whichHeap = HEAP_DALVIK;
28925c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                        subHeap = HEAP_DALVIK_NON_MOVING;
29025c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                    } else if (strstr(name, "/dev/ashmem/dalvik-zygote space") == name) {
29125c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                        whichHeap = HEAP_DALVIK;
29225c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                        subHeap = HEAP_DALVIK_ZYGOTE;
29325c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                    } else if (strstr(name, "/dev/ashmem/dalvik-indirect ref") == name) {
29425c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                        subHeap = HEAP_DALVIK_INDIRECT_REFERENCE_TABLE;
29564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    } else if (strstr(name, "/dev/ashmem/dalvik-jit-code-cache") == name) {
29664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                        subHeap = HEAP_DALVIK_CODE_CACHE;
29764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    } else {
298eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                        subHeap = HEAP_DALVIK_ACCOUNTING;  // Default to accounting.
29964770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    }
30064770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                } else if (strncmp(name, "/dev/ashmem/CursorWindow", 24) == 0) {
30164770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    whichHeap = HEAP_CURSOR;
30264770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                } else if (strncmp(name, "/dev/ashmem/libc malloc", 23) == 0) {
30364770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    whichHeap = HEAP_NATIVE;
30464770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                } else {
30564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                    whichHeap = HEAP_ASHMEM;
30664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                }
307cb4728f247e3793e7fc1baa031290aa732bb77a7Colin Cross            } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
3080e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_NATIVE;
30964770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            } else if (strncmp(name, "[stack", 6) == 0) {
3107c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                whichHeap = HEAP_STACK;
31164770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            } else if (strncmp(name, "/dev/", 5) == 0) {
312184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn                if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
313184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn                    whichHeap = HEAP_GL_DEV;
314184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn                } else {
315184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn                    whichHeap = HEAP_UNKNOWN_DEV;
316184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn                }
3170e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
3180e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_SO;
3193c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
3200e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) {
3210e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_JAR;
3223c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
3230e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) {
3240e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_APK;
3253c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
3260e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
3270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_TTF;
3283c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
3299f8589c31f8910a9c3c33a81675822da9f0cf2dfIan Rogers            } else if ((nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) ||
3309f8589c31f8910a9c3c33a81675822da9f0cf2dfIan Rogers                       (nameLen > 5 && strcmp(name+nameLen-5, ".odex") == 0)) {
3310e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_DEX;
3323c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
3338884ef4fe80505bc6e41c167b67efbb93e43475dAnwar Ghuloum            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".oat") == 0) {
3348884ef4fe80505bc6e41c167b67efbb93e43475dAnwar Ghuloum                whichHeap = HEAP_OAT;
3353c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
33688887d0a53f866e61a7524b0edfc95e6dde57d72Anwar Ghuloum            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
33788887d0a53f866e61a7524b0edfc95e6dde57d72Anwar Ghuloum                whichHeap = HEAP_ART;
3383c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                is_swappable = true;
339cb4728f247e3793e7fc1baa031290aa732bb77a7Colin Cross            } else if (strncmp(name, "[anon:", 6) == 0) {
340cb4728f247e3793e7fc1baa031290aa732bb77a7Colin Cross                whichHeap = HEAP_UNKNOWN;
3410e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (nameLen > 0) {
3420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_UNKNOWN_MAP;
3430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else if (start == prevEnd && prevHeap == HEAP_SO) {
3440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                // bss section of a shared library.
3450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                whichHeap = HEAP_SO;
3460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3496215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        //ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //    isSqliteHeap, line);
3517c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
3528883ced18ac25199330843964634fdf70647a127Dianne Hackborn        shared_clean = 0;
3538883ced18ac25199330843964634fdf70647a127Dianne Hackborn        shared_dirty = 0;
3548883ced18ac25199330843964634fdf70647a127Dianne Hackborn        private_clean = 0;
3558883ced18ac25199330843964634fdf70647a127Dianne Hackborn        private_dirty = 0;
3568883ced18ac25199330843964634fdf70647a127Dianne Hackborn        swapped_out = 0;
3578883ced18ac25199330843964634fdf70647a127Dianne Hackborn
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (true) {
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fgets(line, 1024, fp) == 0) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                done = true;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3648883ced18ac25199330843964634fdf70647a127Dianne Hackborn            if (line[0] == 'S' && sscanf(line, "Size: %d kB", &temp) == 1) {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                size = temp;
3668883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'R' && sscanf(line, "Rss: %d kB", &temp) == 1) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                resident = temp;
3688883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'P' && sscanf(line, "Pss: %d kB", &temp) == 1) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pss = temp;
3708883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'S' && sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                shared_clean = temp;
3728883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'S' && sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                shared_dirty = temp;
3748883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'P' && sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                private_clean = temp;
3768883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'P' && sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                private_dirty = temp;
3788883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'R' && sscanf(line, "Referenced: %d kB", &temp) == 1) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                referenced = temp;
3808883ced18ac25199330843964634fdf70647a127Dianne Hackborn            } else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
3818883ced18ac25199330843964634fdf70647a127Dianne Hackborn                swapped_out = temp;
3820c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross            } else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // looks like a new mapping
384bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba                // example: "10000000-10001000 ---p 10000000 00:00 0"
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!skip) {
3903c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            if (is_swappable && (pss > 0)) {
3913c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                sharing_proportion = 0.0;
3923c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                if ((shared_clean > 0) || (shared_dirty > 0)) {
3938883ced18ac25199330843964634fdf70647a127Dianne Hackborn                    sharing_proportion = (pss - private_clean
3948883ced18ac25199330843964634fdf70647a127Dianne Hackborn                            - private_dirty)/(shared_clean+shared_dirty);
3953c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                }
3963c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                swappable_pss = (sharing_proportion*shared_clean) + private_clean;
3973c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            } else
3983c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                swappable_pss = 0;
3993c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
4000e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            stats[whichHeap].pss += pss;
4013c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            stats[whichHeap].swappablePss += swappable_pss;
4020e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            stats[whichHeap].privateDirty += private_dirty;
4030e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            stats[whichHeap].sharedDirty += shared_dirty;
4043c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            stats[whichHeap].privateClean += private_clean;
4053a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum            stats[whichHeap].sharedClean += shared_clean;
4068883ced18ac25199330843964634fdf70647a127Dianne Hackborn            stats[whichHeap].swappedOut += swapped_out;
40764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            if (whichHeap == HEAP_DALVIK || whichHeap == HEAP_DALVIK_OTHER) {
4083c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                stats[subHeap].pss += pss;
4093c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                stats[subHeap].swappablePss += swappable_pss;
4103c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                stats[subHeap].privateDirty += private_dirty;
4113c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                stats[subHeap].sharedDirty += shared_dirty;
4123c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                stats[subHeap].privateClean += private_clean;
4133c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                stats[subHeap].sharedClean += shared_clean;
4148883ced18ac25199330843964634fdf70647a127Dianne Hackborn                stats[subHeap].swappedOut += swapped_out;
4153c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void load_maps(int pid, stats_t* stats)
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char tmp[128];
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE *fp;
4247c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sprintf(tmp, "/proc/%d/smaps", pid);
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fp = fopen(tmp, "r");
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == 0) return;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    read_mapinfo(fp, stats);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fclose(fp);
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4333025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
4343025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn        jint pid, jobject object)
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    stats_t stats[_NUM_HEAP];
4370e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    memset(&stats, 0, sizeof(stats));
4387c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
4390e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    load_maps(pid, stats);
4400e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4415b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    struct graphics_memory_pss graphics_mem;
4425b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (read_memtrack_memory(pid, &graphics_mem) == 0) {
4435b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        stats[HEAP_GRAPHICS].pss = graphics_mem.graphics;
4445b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        stats[HEAP_GRAPHICS].privateDirty = graphics_mem.graphics;
4455b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        stats[HEAP_GL].pss = graphics_mem.gl;
4465b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        stats[HEAP_GL].privateDirty = graphics_mem.gl;
4475b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        stats[HEAP_OTHER_MEMTRACK].pss = graphics_mem.other;
4485b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        stats[HEAP_OTHER_MEMTRACK].privateDirty = graphics_mem.other;
4495b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
45037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
4513c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    for (int i=_NUM_CORE_HEAP; i<_NUM_EXCLUSIVE_HEAP; i++) {
4520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stats[HEAP_UNKNOWN].pss += stats[i].pss;
4533c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        stats[HEAP_UNKNOWN].swappablePss += stats[i].swappablePss;
4540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty;
4550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
4563c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        stats[HEAP_UNKNOWN].privateClean += stats[i].privateClean;
4573a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        stats[HEAP_UNKNOWN].sharedClean += stats[i].sharedClean;
4588883ced18ac25199330843964634fdf70647a127Dianne Hackborn        stats[HEAP_UNKNOWN].swappedOut += stats[i].swappedOut;
4590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4610e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=0; i<_NUM_CORE_HEAP; i++) {
4620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss);
4633c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        env->SetIntField(object, stat_fields[i].pssSwappable_field, stats[i].swappablePss);
4640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
4650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
4663c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        env->SetIntField(object, stat_fields[i].privateClean_field, stats[i].privateClean);
4673a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        env->SetIntField(object, stat_fields[i].sharedClean_field, stats[i].sharedClean);
4688883ced18ac25199330843964634fdf70647a127Dianne Hackborn        env->SetIntField(object, stat_fields[i].swappedOut_field, stats[i].swappedOut);
4690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
4707c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
4713c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
4720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
4737c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
4740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
4750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if (otherArray == NULL) {
4760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        return;
4770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
4780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int j=0;
4800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
4810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        otherArray[j++] = stats[i].pss;
4823c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        otherArray[j++] = stats[i].swappablePss;
4830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        otherArray[j++] = stats[i].privateDirty;
4840e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        otherArray[j++] = stats[i].sharedDirty;
4853c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        otherArray[j++] = stats[i].privateClean;
4863a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        otherArray[j++] = stats[i].sharedClean;
4878883ced18ac25199330843964634fdf70647a127Dianne Hackborn        otherArray[j++] = stats[i].swappedOut;
4880e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
4890e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4900e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4933025ef332c29e255388f74b2afefe05f64bce07cDianne Hackbornstatic void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
4943025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn{
4953025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
4963025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn}
4973025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn
4981a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackbornstatic jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, jlongArray outUss,
4991a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        jlongArray outMemtrack)
500b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn{
501b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    char line[1024];
502b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    jlong pss = 0;
503c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn    jlong uss = 0;
5041a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    jlong memtrack = 0;
505b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    unsigned temp;
506b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
507b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    char tmp[128];
508b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    FILE *fp;
509b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
5105b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    struct graphics_memory_pss graphics_mem;
5115b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (read_memtrack_memory(pid, &graphics_mem) == 0) {
5121a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        pss = uss = memtrack = graphics_mem.graphics + graphics_mem.gl + graphics_mem.other;
5135b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
51437c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
515b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    sprintf(tmp, "/proc/%d/smaps", pid);
516b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    fp = fopen(tmp, "r");
517b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
51837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    if (fp != 0) {
51937c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        while (true) {
52037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            if (fgets(line, 1024, fp) == NULL) {
52137c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                break;
52237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            }
523b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
52437c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            if (line[0] == 'P') {
52537c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                if (strncmp(line, "Pss:", 4) == 0) {
52637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    char* c = line + 4;
52737c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    while (*c != 0 && (*c < '0' || *c > '9')) {
52837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                        c++;
52937c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    }
53037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    pss += atoi(c);
53145838de942b87150fc3b03a8b943841a8647fd81Iliyan Malchev                } else if (strncmp(line, "Private_Clean:", 14) == 0
53245838de942b87150fc3b03a8b943841a8647fd81Iliyan Malchev                        || strncmp(line, "Private_Dirty:", 14) == 0) {
53337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    char* c = line + 14;
53437c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    while (*c != 0 && (*c < '0' || *c > '9')) {
53537c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                        c++;
53637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    }
53737c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    uss += atoi(c);
538c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn                }
539cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn            }
540b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
541b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
54237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        fclose(fp);
543b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    }
544b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
545c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn    if (outUss != NULL) {
546c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn        if (env->GetArrayLength(outUss) >= 1) {
547c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn            jlong* outUssArray = env->GetLongArrayElements(outUss, 0);
548c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn            if (outUssArray != NULL) {
549c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn                outUssArray[0] = uss;
550c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn            }
551c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn            env->ReleaseLongArrayElements(outUss, outUssArray, 0);
552c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn        }
553c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn    }
554b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
5551a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    if (outMemtrack != NULL) {
5561a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        if (env->GetArrayLength(outMemtrack) >= 1) {
5571a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn            jlong* outMemtrackArray = env->GetLongArrayElements(outMemtrack, 0);
5581a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn            if (outMemtrackArray != NULL) {
5591a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn                outMemtrackArray[0] = memtrack;
5601a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn            }
5611a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn            env->ReleaseLongArrayElements(outMemtrack, outMemtrackArray, 0);
5621a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        }
5631a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    }
5641a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn
565b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    return pss;
566b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn}
567b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
568b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackbornstatic jlong android_os_Debug_getPss(JNIEnv *env, jobject clazz)
569b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn{
5701a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    return android_os_Debug_getPssPid(env, clazz, getpid(), NULL, NULL);
571b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn}
572b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
573cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackbornenum {
574cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_TOTAL,
575cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_FREE,
576cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_BUFFERS,
577cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_CACHED,
578cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_SHMEM,
579cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_SLAB,
580cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_SWAP_TOTAL,
581cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_SWAP_FREE,
582cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_ZRAM_TOTAL,
583b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    MEMINFO_MAPPED,
584b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    MEMINFO_VMALLOC_USED,
585b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    MEMINFO_PAGE_TABLES,
586b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    MEMINFO_KERNEL_STACK,
587cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    MEMINFO_COUNT
588cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn};
589cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn
5908e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackbornstatic void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray out)
5918e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn{
5928e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    char buffer[1024];
5938e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    int numFound = 0;
5948e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
5958e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (out == NULL) {
5968e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        jniThrowNullPointerException(env, "out == null");
5978e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return;
5988e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
5998e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6008e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    int fd = open("/proc/meminfo", O_RDONLY);
6018e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6028e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (fd < 0) {
603cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        ALOGW("Unable to open /proc/meminfo: %s\n", strerror(errno));
6048e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return;
6058e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6068e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
607cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    int len = read(fd, buffer, sizeof(buffer)-1);
6088e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    close(fd);
6098e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6108e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (len < 0) {
611cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        ALOGW("Empty /proc/meminfo");
6128e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return;
6138e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6148e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    buffer[len] = 0;
6158e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6168e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    static const char* const tags[] = {
6178e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            "MemTotal:",
6188e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            "MemFree:",
6198e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            "Buffers:",
6208e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            "Cached:",
6218e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            "Shmem:",
6228e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            "Slab:",
623cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            "SwapTotal:",
624cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            "SwapFree:",
625b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            "ZRam:",
626b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            "Mapped:",
627b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            "VmallocUsed:",
628b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            "PageTables:",
629b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            "KernelStack:",
6308e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            NULL
6318e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    };
6328e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    static const int tagsLen[] = {
6338e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            9,
6348e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            8,
6358e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            8,
6368e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            7,
6378e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            6,
6388e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            5,
639cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            10,
640cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            9,
641b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            5,
642b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            7,
643b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            12,
644b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            11,
645b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            12,
6468e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            0
6478e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    };
648b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    long mem[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
6498e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6508e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    char* p = buffer;
651b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    while (*p && numFound < 13) {
6528e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        int i = 0;
6538e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        while (tags[i]) {
6548e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            if (strncmp(p, tags[i], tagsLen[i]) == 0) {
6558e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                p += tagsLen[i];
6568e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                while (*p == ' ') p++;
6578e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                char* num = p;
6588e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                while (*p >= '0' && *p <= '9') p++;
6598e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                if (*p != 0) {
6608e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                    *p = 0;
6618e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                    p++;
6628e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                }
6638e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                mem[i] = atoll(num);
6648e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                numFound++;
6658e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                break;
6668e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            }
6678e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            i++;
6688e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6698e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        while (*p && *p != '\n') {
6708e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            p++;
6718e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6728e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        if (*p) p++;
6738e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6748e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
675cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    fd = open("/sys/block/zram0/mem_used_total", O_RDONLY);
676cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    if (fd >= 0) {
677cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        len = read(fd, buffer, sizeof(buffer)-1);
678cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        close(fd);
679cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        if (len > 0) {
680cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            buffer[len] = 0;
681cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn            mem[MEMINFO_ZRAM_TOTAL] = atoll(buffer)/1024;
682cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        }
683cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    }
684cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn
6858e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    int maxNum = env->GetArrayLength(out);
686cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    if (maxNum > MEMINFO_COUNT) {
687cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        maxNum = MEMINFO_COUNT;
688cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    }
6898e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    jlong* outArray = env->GetLongArrayElements(out, 0);
6908e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (outArray != NULL) {
691cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn        for (int i=0; i<maxNum; i++) {
6928e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            outArray[i] = mem[i];
6938e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6948e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6958e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    env->ReleaseLongArrayElements(out, outArray, 0);
696b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn}
697b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint read_binder_stat(const char* stat)
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FILE* fp = fopen(BINDER_STATS, "r");
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fp == NULL) {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char line[1024];
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char compare[128];
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int len = snprintf(compare, 128, "proc %d", getpid());
7097c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // loop until we have the block that represents this process
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fgets(line, 1024, fp) == 0) {
713c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes            fclose(fp);
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (strncmp(compare, line, len));
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7187c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    // now that we have this process, read until we find the stat that we are looking for
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    len = snprintf(compare, 128, "  %s: ", stat);
7207c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (fgets(line, 1024, fp) == 0) {
723c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes            fclose(fp);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (strncmp(compare, line, len));
7277c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // we have the line, now increment the line ptr to the value
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char* ptr = line + len;
730c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes    jint result = atoi(ptr);
731c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes    fclose(fp);
732c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes    return result;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_Debug_getBinderSentTransactions(JNIEnv *env, jobject clazz)
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read_binder_stat("bcTRANSACTION");
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_os_getBinderReceivedTransactions(JNIEnv *env, jobject clazz)
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read_binder_stat("brTRANSACTION");
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// these are implemented in android_util_Binder.cpp
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz);
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
75006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
75106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/* pulled out of bionic */
75206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
75306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
75406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenextern "C" void free_malloc_leak_info(uint8_t* info);
75506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define SIZE_FLAG_ZYGOTE_CHILD  (1<<31)
75606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#define BACKTRACE_SIZE          32
75706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
75806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
75906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * This is a qsort() callback.
76006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
76106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * See dumpNativeHeap() for comments about the data format and sort order.
76206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
76306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic int compareHeapRecords(const void* vrec1, const void* vrec2)
76406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
76506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const size_t* rec1 = (const size_t*) vrec1;
76606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const size_t* rec2 = (const size_t*) vrec2;
76706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t size1 = *rec1;
76806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t size2 = *rec2;
76906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
77006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (size1 < size2) {
77106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return 1;
77206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    } else if (size1 > size2) {
77306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return -1;
77406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
77506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
77606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    intptr_t* bt1 = (intptr_t*)(rec1 + 2);
77706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    intptr_t* bt2 = (intptr_t*)(rec2 + 2);
77806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    for (size_t idx = 0; idx < BACKTRACE_SIZE; idx++) {
77906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t addr1 = bt1[idx];
78006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t addr2 = bt2[idx];
78106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (addr1 == addr2) {
78206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (addr1 == 0)
78306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                break;
78406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            continue;
78506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
78606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (addr1 < addr2) {
78706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return -1;
78806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        } else if (addr1 > addr2) {
78906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return 1;
79006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
79106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
79206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
79306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    return 0;
79406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
79506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
79606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
79706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The get_malloc_leak_info() call returns an array of structs that
79806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * look like this:
79906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
80006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   size_t size
80106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   size_t allocations
80206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *   intptr_t backtrace[32]
80306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
80406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * "size" is the size of the allocation, "backtrace" is a fixed-size
80506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * array of function pointers, and "allocations" is the number of
80606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * allocations with the exact same size and backtrace.
80706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden *
80806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * The entries are sorted by descending total size (i.e. size*allocations)
80906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * then allocation count.  For best results with "diff" we'd like to sort
81006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * primarily by individual size then stack trace.  Since the entries are
81106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * fixed-size, and we're allowed (by the current implementation) to mangle
81206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * them, we can do this in place.
81306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
81406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void dumpNativeHeap(FILE* fp)
81506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
81606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    uint8_t* info = NULL;
81706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t overallSize, infoSize, totalMemory, backtraceSize;
81806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
81906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory,
82006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        &backtraceSize);
82106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (info == NULL) {
82206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "Native heap dump not available. To enable, run these"
82306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    " commands (requires root):\n");
82406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell setprop libc.debug.malloc 1\n");
82506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell stop\n");
82606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "$ adb shell start\n");
82706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
82806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
82906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    assert(infoSize != 0);
83006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    assert(overallSize % infoSize == 0);
83106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
83206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Android Native Heap Dump v1.0\n\n");
83306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
83406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t recordCount = overallSize / infoSize;
83506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Total memory: %zu\n", totalMemory);
83606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "Allocation records: %zd\n", recordCount);
83706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (backtraceSize != BACKTRACE_SIZE) {
838f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        fprintf(fp, "WARNING: mismatched backtrace sizes (%zu vs. %d)\n",
83906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            backtraceSize, BACKTRACE_SIZE);
84006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
84106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fprintf(fp, "\n");
84206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
84306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* re-sort the entries */
84406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    qsort(info, recordCount, infoSize, compareHeapRecords);
84506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
84606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* dump the entries to the file */
84706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const uint8_t* ptr = info;
84806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    for (size_t idx = 0; idx < recordCount; idx++) {
84906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        size_t size = *(size_t*) ptr;
85006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        size_t allocations = *(size_t*) (ptr + sizeof(size_t));
85106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        intptr_t* backtrace = (intptr_t*) (ptr + sizeof(size_t) * 2);
85206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
85306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "z %d  sz %8zu  num %4zu  bt",
85406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                (size & SIZE_FLAG_ZYGOTE_CHILD) != 0,
85506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                size & ~SIZE_FLAG_ZYGOTE_CHILD,
85606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                allocations);
85706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        for (size_t bt = 0; bt < backtraceSize; bt++) {
85806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (backtrace[bt] == 0) {
85906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                break;
86006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            } else {
861f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat#ifdef __LP64__
862853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn                fprintf(fp, " %016" PRIxPTR, backtrace[bt]);
863f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat#else
864853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn                fprintf(fp, " %08" PRIxPTR, backtrace[bt]);
865f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat#endif
86606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
86706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
86806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        fprintf(fp, "\n");
86906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
87006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        ptr += infoSize;
87106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
87206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
87306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    free_malloc_leak_info(info);
874393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
875393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fprintf(fp, "MAPS\n");
876393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    const char* maps = "/proc/self/maps";
877393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    FILE* in = fopen(maps, "r");
878393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    if (in == NULL) {
879393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        fprintf(fp, "Could not open %s\n", maps);
880393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        return;
881393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    }
882393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    char buf[BUFSIZ];
883393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) {
884393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom        fwrite(buf, sizeof(char), n, fp);
885393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    }
886393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fclose(in);
887393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
888393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom    fprintf(fp, "END\n");
88906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
89006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
89106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden/*
89206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * Dump the native heap, writing human-readable output to the specified
89306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden * file descriptor.
89406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden */
89506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
89606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    jobject fileDescriptor)
89706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden{
89806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fileDescriptor == NULL) {
8997c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        jniThrowNullPointerException(env, "fd == null");
90006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
90106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
90206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
90306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (origFd < 0) {
90406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "Invalid file descriptor");
90506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
90606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
90706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
90806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    /* dup() the descriptor so we don't close the original with fclose() */
90906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    int fd = dup(origFd);
91006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fd < 0) {
9118564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("dup(%d) failed: %s\n", origFd, strerror(errno));
91206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "dup() failed");
91306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
91406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
91506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
91606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    FILE* fp = fdopen(fd, "w");
91706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (fp == NULL) {
9188564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("fdopen(%d) failed: %s\n", fd, strerror(errno));
91906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        close(fd);
92006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        jniThrowRuntimeException(env, "fdopen() failed");
92106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return;
92206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
92306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
9245baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("Native heap dump starting...\n");
92506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    dumpNativeHeap(fp);
9265baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("Native heap dump complete.\n");
92706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
92806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    fclose(fp);
92906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
93006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
93106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
932f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackbornstatic void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject clazz,
933f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    jint pid, jstring fileName)
934f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn{
935f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (fileName == NULL) {
9367c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        jniThrowNullPointerException(env, "file == null");
937f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        return;
938f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
939f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    const jchar* str = env->GetStringCritical(fileName, 0);
940f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    String8 fileName8;
941f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (str) {
942f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        fileName8 = String8(str, env->GetStringLength(fileName));
943f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        env->ReleaseStringCritical(fileName, str);
944f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
945f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
946f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666);  /* -rw-rw-rw- */
947f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (fd < 0) {
948f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        fprintf(stderr, "Can't open %s: %s\n", fileName8.string(), strerror(errno));
949f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        return;
950f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
951f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
952f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    if (lseek(fd, 0, SEEK_END) < 0) {
953f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        fprintf(stderr, "lseek: %s\n", strerror(errno));
954f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    } else {
955f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        dump_backtrace_to_file(pid, fd);
956f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    }
957f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
958f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    close(fd);
959f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn}
960f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration.
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapSize",      "()J",
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapSize },
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapAllocatedSize", "()J",
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapAllocatedSize },
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getNativeHeapFreeSize",  "()J",
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getNativeHeapFreeSize },
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getMemoryInfo",          "(Landroid/os/Debug$MemoryInfo;)V",
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getDirtyPages },
9743025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn    { "getMemoryInfo",          "(ILandroid/os/Debug$MemoryInfo;)V",
9753025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            (void*) android_os_Debug_getDirtyPagesPid },
976b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    { "getPss",                 "()J",
977b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            (void*) android_os_Debug_getPss },
9781a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    { "getPss",                 "(I[J[J)J",
979b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            (void*) android_os_Debug_getPssPid },
9808e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    { "getMemInfo",             "([J)V",
9818e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            (void*) android_os_Debug_getMemInfo },
98206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    { "dumpNativeHeap",         "(Ljava/io/FileDescriptor;)V",
98306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            (void*) android_os_Debug_dumpNativeHeap },
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderSentTransactions", "()I",
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_Debug_getBinderSentTransactions },
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderReceivedTransactions", "()I",
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*) android_os_getBinderReceivedTransactions },
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderLocalObjectCount", "()I",
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getLocalObjectCount },
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderProxyObjectCount", "()I",
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getProxyObjectCount },
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "getBinderDeathObjectCount", "()I",
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (void*)android_os_Debug_getDeathObjectCount },
994f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn    { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
995f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            (void*)android_os_Debug_dumpNativeBacktraceToFile },
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_Debug(JNIEnv *env)
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
10005b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    int err = memtrack_init();
10015b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (err != 0) {
10025b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        memtrackLoaded = false;
10035b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        ALOGE("failed to load memtrack module: %d", err);
10045b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    } else {
10055b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        memtrackLoaded = true;
10065b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
10075b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10107c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    // Sanity check the number of other statistics expected in Java matches here.
10117c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    jfieldID numOtherStats_field = env->GetStaticFieldID(clazz, "NUM_OTHER_STATS", "I");
10127c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    jint numOtherStats = env->GetStaticIntField(clazz, numOtherStats_field);
10133c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    jfieldID numDvkStats_field = env->GetStaticFieldID(clazz, "NUM_DVK_STATS", "I");
10143c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    jint numDvkStats = env->GetStaticIntField(clazz, numDvkStats_field);
10157c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    int expectedNumOtherStats = _NUM_HEAP - _NUM_CORE_HEAP;
10163c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    if ((numOtherStats + numDvkStats) != expectedNumOtherStats) {
10177c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
10183c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                             "android.os.Debug.Meminfo.NUM_OTHER_STATS+android.os.Debug.Meminfo.NUM_DVK_STATS=%d expected %d",
10193c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                             numOtherStats+numDvkStats, expectedNumOtherStats);
10207c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        return JNI_ERR;
10217c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    }
10227c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
10237c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
10247c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
10250e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    for (int i=0; i<_NUM_CORE_HEAP; i++) {
10260e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stat_fields[i].pss_field =
10270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
10283c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        stat_fields[i].pssSwappable_field =
10293c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                env->GetFieldID(clazz, stat_field_names[i].pssSwappable_name, "I");
10300e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stat_fields[i].privateDirty_field =
10310e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I");
10320e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        stat_fields[i].sharedDirty_field =
10330e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I");
10343c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        stat_fields[i].privateClean_field =
10353c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                env->GetFieldID(clazz, stat_field_names[i].privateClean_name, "I");
10363a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        stat_fields[i].sharedClean_field =
10373a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum                env->GetFieldID(clazz, stat_field_names[i].sharedClean_name, "I");
10388883ced18ac25199330843964634fdf70647a127Dianne Hackborn        stat_fields[i].swappedOut_field =
10398883ced18ac25199330843964634fdf70647a127Dianne Hackborn                env->GetFieldID(clazz, stat_field_names[i].swappedOut_name, "I");
10400e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
10410e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}; // namespace android
1046