Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1078609d authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Rework and fix "adb shell dumpsys meminfo""

parents 9c7b5ec0 0e3328fb
Loading
Loading
Loading
Loading
+59 −39
Original line number Diff line number Diff line
@@ -413,10 +413,10 @@ public final class ActivityThread {
    native private void dumpGraphicsInfo(FileDescriptor fd);

    private final class ApplicationThread extends ApplicationThreadNative {
        private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
        private static final String ONE_COUNT_COLUMN = "%17s %8d";
        private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
        private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
        private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s";
        private static final String ONE_COUNT_COLUMN = "%21s %8d";
        private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
        private static final String TWO_COUNT_COLUMNS_DB = "%21s %8d %21s %8d";
        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

        // Formatting for checkin service - update version if row format changes
@@ -729,12 +729,17 @@ public final class ActivityThread {
        }

        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (args != null && args.length == 1 && args[0].equals("graphics")) {
        public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) {
            FileOutputStream fout = new FileOutputStream(fd);
            PrintWriter pw = new PrintWriter(fout);
            try {
                return dumpMemInfo(fd, pw, args);
            } finally {
                pw.flush();
                dumpGraphicsInfo(fd);
                return;
            }
        }

        private Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
            long nativeMax = Debug.getNativeHeapSize() / 1024;
            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -742,14 +747,6 @@ public final class ActivityThread {
            Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
            Debug.getMemoryInfo(memInfo);

            final int nativeShared = memInfo.nativeSharedDirty;
            final int dalvikShared = memInfo.dalvikSharedDirty;
            final int otherShared = memInfo.otherSharedDirty;

            final int nativePrivate = memInfo.nativePrivateDirty;
            final int dalvikPrivate = memInfo.dalvikPrivateDirty;
            final int otherPrivate = memInfo.otherPrivateDirty;

            Runtime runtime = Runtime.getRuntime();

            long dalvikMax = runtime.totalMemory() / 1024;
@@ -813,16 +810,18 @@ public final class ActivityThread {
                pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');

                // Heap info - shared
                pw.print(nativeShared); pw.print(',');
                pw.print(dalvikShared); pw.print(',');
                pw.print(otherShared); pw.print(',');
                pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
                pw.print(memInfo.nativeSharedDirty); pw.print(',');
                pw.print(memInfo.dalvikSharedDirty); pw.print(',');
                pw.print(memInfo.otherSharedDirty); pw.print(',');
                pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty
                        + memInfo.otherSharedDirty); pw.print(',');

                // Heap info - private
                pw.print(nativePrivate); pw.print(',');
                pw.print(dalvikPrivate); pw.print(',');
                pw.print(otherPrivate); pw.print(',');
                pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
                pw.print(memInfo.nativePrivateDirty); pw.print(',');
                pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
                pw.print(memInfo.otherPrivateDirty); pw.print(',');
                pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty
                        + memInfo.otherPrivateDirty); pw.print(',');

                // Object counts
                pw.print(viewInstanceCount); pw.print(',');
@@ -850,25 +849,39 @@ public final class ActivityThread {
                    pw.print(',');
                }

                return;
                return memInfo;
            }

            // otherwise, show human-readable format
            printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
            printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
            printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
                    nativeAllocated + dalvikAllocated);
            printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
            printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap");
            printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free");
            printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------",
                    "------");
            printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty,
                    memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree);
            printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty,
                    memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree);

            int otherPss = memInfo.otherPss;
            int otherSharedDirty = memInfo.otherSharedDirty;
            int otherPrivateDirty = memInfo.otherPrivateDirty;

            for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
                printRow(pw, HEAP_COLUMN, memInfo.getOtherLabel(i),
                        memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i),
                        memInfo.getOtherPrivateDirty(i), "", "", "");
                otherPss -= memInfo.getOtherPss(i);
                otherSharedDirty -= memInfo.getOtherSharedDirty(i);
                otherPrivateDirty -= memInfo.getOtherPrivateDirty(i);
            }

            printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty,
                    otherPrivateDirty, "", "", "");
            printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
                    memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
                    nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
                    nativeFree+dalvikFree);

            printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
                    memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);

            printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
                    nativeShared + dalvikShared + otherShared);
            printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
                    nativePrivate + dalvikPrivate + otherPrivate);

            pw.println(" ");
            pw.println(" Objects");
            printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewAncestors:",
@@ -916,6 +929,13 @@ public final class ActivityThread {
                pw.println(" Asset Allocations");
                pw.print(assetAlloc);
            }

            return memInfo;
        }

        @Override
        public void dumpGfxInfo(FileDescriptor fd, String[] args) {
            dumpGraphicsInfo(fd);
        }

        private void printRow(PrintWriter pw, String format, Object...objs) {
+66 −0
Original line number Diff line number Diff line
@@ -485,6 +485,48 @@ public abstract class ApplicationThreadNative extends Binder
            scheduleTrimMemory(level);
            return true;
        }

        case DUMP_MEM_INFO_TRANSACTION:
        {
            data.enforceInterface(IApplicationThread.descriptor);
            ParcelFileDescriptor fd = data.readFileDescriptor();
            String[] args = data.readStringArray();
            Debug.MemoryInfo mi = null;
            if (fd != null) {
                try {
                    mi = dumpMemInfo(fd.getFileDescriptor(), args);
                } finally {
                    try {
                        fd.close();
                    } catch (IOException e) {
                        // swallowed, not propagated back to the caller
                    }
                }
            }
            reply.writeNoException();
            mi.writeToParcel(reply, 0);
            return true;
        }

        case DUMP_GFX_INFO_TRANSACTION:
        {
            data.enforceInterface(IApplicationThread.descriptor);
            ParcelFileDescriptor fd = data.readFileDescriptor();
            String[] args = data.readStringArray();
            if (fd != null) {
                try {
                    dumpGfxInfo(fd.getFileDescriptor(), args);
                } finally {
                    try {
                        fd.close();
                    } catch (IOException e) {
                        // swallowed, not propagated back to the caller
                    }
                }
            }
            reply.writeNoException();
            return true;
        }
        }

        return super.onTransact(code, data, reply, flags);
@@ -1004,4 +1046,28 @@ class ApplicationThreadProxy implements IApplicationThread {
        mRemote.transact(SCHEDULE_TRIM_MEMORY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
    }

    public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeFileDescriptor(fd);
        data.writeStringArray(args);
        mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
        reply.readException();
        Debug.MemoryInfo info = new Debug.MemoryInfo();
        info.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return info;
    }

    public void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeFileDescriptor(fd);
        data.writeStringArray(args);
        mRemote.transact(DUMP_GFX_INFO_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
        data.recycle();
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ public interface IApplicationThread extends IInterface {
    void setCoreSettings(Bundle coreSettings) throws RemoteException;
    void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
    void scheduleTrimMemory(int level) throws RemoteException;
    Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException;
    void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;

    String descriptor = "android.app.IApplicationThread";

@@ -164,4 +166,6 @@ public interface IApplicationThread extends IInterface {
    int SET_CORE_SETTINGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+39;
    int UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+40;
    int SCHEDULE_TRIM_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+41;
    int DUMP_MEM_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+42;
    int DUMP_GFX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+43;
}
+39 −0
Original line number Diff line number Diff line
@@ -129,6 +129,11 @@ public final class Debug
        /** The shared dirty pages used by everything else. */
        public int otherSharedDirty;

        /** @hide */
        public static final int NUM_OTHER_STATS = 9;

        private int[] otherStats = new int[NUM_OTHER_STATS*3];

        public MemoryInfo() {
        }

@@ -153,6 +158,38 @@ public final class Debug
            return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
        }

        /* @hide */
        public int getOtherPss(int which) {
            return otherStats[which*3];
        }

        /* @hide */
        public int getOtherPrivateDirty(int which) {
            return otherStats[which*3 + 1];
        }

        /* @hide */
        public int getOtherSharedDirty(int which) {
            return otherStats[which*3 + 2];
        }


        /* @hide */
        public static String getOtherLabel(int which) {
            switch (which) {
                case 0: return "Cursor";
                case 1: return "Ashmem";
                case 2: return "Other dev";
                case 3: return ".so mmap";
                case 4: return ".jar mmap";
                case 5: return ".apk mmap";
                case 6: return ".ttf mmap";
                case 7: return ".dex mmap";
                case 8: return "Other mmap";
                default: return "????";
            }
        }

        public int describeContents() {
            return 0;
        }
@@ -167,6 +204,7 @@ public final class Debug
            dest.writeInt(otherPss);
            dest.writeInt(otherPrivateDirty);
            dest.writeInt(otherSharedDirty);
            dest.writeIntArray(otherStats);
        }

        public void readFromParcel(Parcel source) {
@@ -179,6 +217,7 @@ public final class Debug
            otherPss = source.readInt();
            otherPrivateDirty = source.readInt();
            otherSharedDirty = source.readInt();
            otherStats = source.createIntArray();
        }

        public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
+134 −85
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <sys/time.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h>

#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -35,28 +36,50 @@
namespace android
{

static jfieldID dalvikPss_field;
static jfieldID dalvikPrivateDirty_field;
static jfieldID dalvikSharedDirty_field;
static jfieldID nativePss_field;
static jfieldID nativePrivateDirty_field;
static jfieldID nativeSharedDirty_field;
static jfieldID otherPss_field;
static jfieldID otherPrivateDirty_field;
static jfieldID otherSharedDirty_field;
enum {
    HEAP_UNKNOWN,
    HEAP_DALVIK,
    HEAP_NATIVE,
    HEAP_CURSOR,
    HEAP_ASHMEM,
    HEAP_UNKNOWN_DEV,
    HEAP_SO,
    HEAP_JAR,
    HEAP_APK,
    HEAP_TTF,
    HEAP_DEX,
    HEAP_UNKNOWN_MAP,

    _NUM_HEAP,
    _NUM_CORE_HEAP = HEAP_NATIVE+1
};

struct stats_t {
    int dalvikPss;
    int dalvikPrivateDirty;
    int dalvikSharedDirty;
struct stat_fields {
    jfieldID pss_field;
    jfieldID privateDirty_field;
    jfieldID sharedDirty_field;
};

    int nativePss;
    int nativePrivateDirty;
    int nativeSharedDirty;
struct stat_field_names {
    const char* pss_name;
    const char* privateDirty_name;
    const char* sharedDirty_name;
};

    int otherPss;
    int otherPrivateDirty;
    int otherSharedDirty;
static stat_fields stat_fields[_NUM_CORE_HEAP];

static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
    { "otherPss", "otherPrivateDirty", "otherSharedDirty" },
    { "dalvikPss", "dalvikPrivateDirty", "dalvikSharedDirty" },
    { "nativePss", "nativePrivateDirty", "nativeSharedDirty" }
};

jfieldID otherStats_field;

struct stats_t {
    int pss;
    int privateDirty;
    int sharedDirty;
};

#define BINDER_STATS "/proc/binder/stats"
@@ -94,48 +117,71 @@ static jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
static void read_mapinfo(FILE *fp, stats_t* stats)
{
    char line[1024];
    int len;
    int len, nameLen;
    bool skip, done = false;

    unsigned start = 0, size = 0, resident = 0, pss = 0;
    unsigned size = 0, resident = 0, pss = 0;
    unsigned shared_clean = 0, shared_dirty = 0;
    unsigned private_clean = 0, private_dirty = 0;
    unsigned referenced = 0;
    unsigned temp;

    int isNativeHeap;
    int isDalvikHeap;
    int isSqliteHeap;
    unsigned long int start;
    unsigned long int end = 0;
    unsigned long int prevEnd = 0;
    char* name;
    int name_pos;

    int whichHeap = HEAP_UNKNOWN;
    int prevHeap = HEAP_UNKNOWN;

    if(fgets(line, 1024, fp) == 0) return;
    if(fgets(line, sizeof(line), fp) == 0) return;

    while (!done) {
        isNativeHeap = 0;
        isDalvikHeap = 0;
        isSqliteHeap = 0;
        prevHeap = whichHeap;
        prevEnd = end;
        whichHeap = HEAP_UNKNOWN;
        skip = false;

        len = strlen(line);
        if (len < 1) return;
        line[--len] = 0;

        /* ignore guard pages */
        if (len > 18 && line[17] == '-') skip = true;

        start = strtoul(line, 0, 16);

        if (strstr(line, "[heap]")) {
            isNativeHeap = 1;
        } else if (strstr(line, "/dalvik-LinearAlloc")) {
            isDalvikHeap = 1;
        } else if (strstr(line, "/mspace/dalvik-heap")) {
            isDalvikHeap = 1;
        } else if (strstr(line, "/dalvik-heap-bitmap/")) {
            isDalvikHeap = 1;    
        } else if (strstr(line, "/data/dalvik-cache/")) {
            isDalvikHeap = 1;
        } else if (strstr(line, "/tmp/sqlite-heap")) {
            isSqliteHeap = 1;
        if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
            skip = true;
        } else {
            while (isspace(line[name_pos])) {
                name_pos += 1;
            }
            name = line + name_pos;
            nameLen = strlen(name);

            if (strstr(name, "[heap]") == name) {
                whichHeap = HEAP_NATIVE;
            } else if (strstr(name, "/dev/ashmem/dalvik-") == name) {
                whichHeap = HEAP_DALVIK;
            } else if (strstr(name, "/dev/ashmem/CursorWindow") == name) {
                whichHeap = HEAP_CURSOR;
            } else if (strstr(name, "/dev/ashmem/") == name) {
                whichHeap = HEAP_ASHMEM;
            } else if (strstr(name, "/dev/") == name) {
                whichHeap = HEAP_UNKNOWN_DEV;
            } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
                whichHeap = HEAP_SO;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) {
                whichHeap = HEAP_JAR;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) {
                whichHeap = HEAP_APK;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
                whichHeap = HEAP_TTF;
            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) {
                whichHeap = HEAP_DEX;
            } else if (nameLen > 0) {
                whichHeap = HEAP_UNKNOWN_MAP;
            } else if (start == prevEnd && prevHeap == HEAP_SO) {
                // bss section of a shared library.
                whichHeap = HEAP_SO;
            }
        }

        //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
@@ -171,21 +217,9 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
        }

        if (!skip) {
            if (isNativeHeap) {
                stats->nativePss += pss;
                stats->nativePrivateDirty += private_dirty;
                stats->nativeSharedDirty += shared_dirty;
            } else if (isDalvikHeap) {
                stats->dalvikPss += pss;
                stats->dalvikPrivateDirty += private_dirty;
                stats->dalvikSharedDirty += shared_dirty;
            } else if ( isSqliteHeap) {
                // ignore
            } else {
                stats->otherPss += pss;
                stats->otherPrivateDirty += private_dirty;
                stats->otherSharedDirty += shared_dirty;
            }
            stats[whichHeap].pss += pss;
            stats[whichHeap].privateDirty += private_dirty;
            stats[whichHeap].sharedDirty += shared_dirty;
        }
    }
}
@@ -206,22 +240,38 @@ static void load_maps(int pid, stats_t* stats)
static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
        jint pid, jobject object)
{
    stats_t stats;
    memset(&stats, 0, sizeof(stats_t));
    stats_t stats[_NUM_HEAP];
    memset(&stats, 0, sizeof(stats));
    
    load_maps(pid, &stats);
    load_maps(pid, stats);

    env->SetIntField(object, dalvikPss_field, stats.dalvikPss);
    env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty);
    env->SetIntField(object, dalvikSharedDirty_field, stats.dalvikSharedDirty);
    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
        stats[HEAP_UNKNOWN].pss += stats[i].pss;
        stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty;
        stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
    }

    env->SetIntField(object, nativePss_field, stats.nativePss);
    env->SetIntField(object, nativePrivateDirty_field, stats.nativePrivateDirty);
    env->SetIntField(object, nativeSharedDirty_field, stats.nativeSharedDirty);
    for (int i=0; i<_NUM_CORE_HEAP; i++) {
        env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss);
        env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
        env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
    }
    
    jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
    
    env->SetIntField(object, otherPss_field, stats.otherPss);
    env->SetIntField(object, otherPrivateDirty_field, stats.otherPrivateDirty);
    env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty);
    jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
    if (otherArray == NULL) {
        return;
    }

    int j=0;
    for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
        otherArray[j++] = stats[i].pss;
        otherArray[j++] = stats[i].privateDirty;
        otherArray[j++] = stats[i].sharedDirty;
    }

    env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
}

static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
@@ -488,17 +538,16 @@ int register_android_os_Debug(JNIEnv *env)
{
    jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");

    dalvikPss_field = env->GetFieldID(clazz, "dalvikPss", "I");
    dalvikPrivateDirty_field = env->GetFieldID(clazz, "dalvikPrivateDirty", "I");
    dalvikSharedDirty_field = env->GetFieldID(clazz, "dalvikSharedDirty", "I");

    nativePss_field = env->GetFieldID(clazz, "nativePss", "I");
    nativePrivateDirty_field = env->GetFieldID(clazz, "nativePrivateDirty", "I");
    nativeSharedDirty_field = env->GetFieldID(clazz, "nativeSharedDirty", "I");
    for (int i=0; i<_NUM_CORE_HEAP; i++) {
        stat_fields[i].pss_field =
                env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
        stat_fields[i].privateDirty_field =
                env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I");
        stat_fields[i].sharedDirty_field =
                env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I");
    }

    otherPss_field = env->GetFieldID(clazz, "otherPss", "I");
    otherPrivateDirty_field = env->GetFieldID(clazz, "otherPrivateDirty", "I");
    otherSharedDirty_field = env->GetFieldID(clazz, "otherSharedDirty", "I");
    otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");

    return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
}
Loading