auto import from //depot/cupcake/@135843
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
new file mode 100644
index 0000000..a6b63d8
--- /dev/null
+++ b/core/jni/android_os_Debug.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include "utils/misc.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+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;
+
+struct stats_t {
+    int dalvikPss;
+    int dalvikPrivateDirty;
+    int dalvikSharedDirty;
+    
+    int nativePss;
+    int nativePrivateDirty;
+    int nativeSharedDirty;
+    
+    int otherPss;
+    int otherPrivateDirty;
+    int otherSharedDirty;
+};
+
+#define BINDER_STATS "/proc/binder/stats"
+
+static jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz)
+{
+#ifdef HAVE_MALLOC_H
+    struct mallinfo info = mallinfo();
+    return (jlong) info.usmblks;
+#else
+    return -1;
+#endif
+}
+
+static jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject clazz)
+{
+#ifdef HAVE_MALLOC_H
+    struct mallinfo info = mallinfo();
+    return (jlong) info.uordblks;
+#else
+    return -1;
+#endif
+}
+
+static jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
+{
+#ifdef HAVE_MALLOC_H    
+    struct mallinfo info = mallinfo();
+    return (jlong) info.fordblks;
+#else
+    return -1;
+#endif
+}
+
+static void read_mapinfo(FILE *fp, stats_t* stats)
+{
+    char line[1024];
+    int len;
+    bool skip, done = false;
+
+    unsigned start = 0, 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;
+
+    if(fgets(line, 1024, fp) == 0) return;
+
+    while (!done) {
+        isNativeHeap = 0;
+        isDalvikHeap = 0;
+        isSqliteHeap = 0;
+        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, "/tmp/sqlite-heap")) {
+            isSqliteHeap = 1;
+        }
+
+        //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
+        //    isSqliteHeap, line);
+            
+        while (true) {
+            if (fgets(line, 1024, fp) == 0) {
+                done = true;
+                break;
+            }
+
+            if (sscanf(line, "Size: %d kB", &temp) == 1) {
+                size = temp;
+            } else if (sscanf(line, "Rss: %d kB", &temp) == 1) {
+                resident = temp;
+            } else if (sscanf(line, "Pss: %d kB", &temp) == 1) {
+                pss = temp;
+            } else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
+                shared_clean = temp;
+            } else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
+                shared_dirty = temp;
+            } else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
+                private_clean = temp;
+            } else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
+                private_dirty = temp;
+            } else if (sscanf(line, "Referenced: %d kB", &temp) == 1) {
+                referenced = temp;
+            } else if (strlen(line) > 40 && line[8] == '-' && line[17] == ' ') {
+                // looks like a new mapping
+                // example: "0000a000-00232000 rwxp 0000a000 00:00 0          [heap]"
+                break;
+            }
+        }
+
+        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 += shared_dirty;
+                stats->otherSharedDirty += private_dirty;
+            }
+        }
+    }
+}
+
+static void load_maps(int pid, stats_t* stats)
+{
+    char tmp[128];
+    FILE *fp;
+    
+    sprintf(tmp, "/proc/%d/smaps", pid);
+    fp = fopen(tmp, "r");
+    if (fp == 0) return;
+
+    read_mapinfo(fp, stats);
+    fclose(fp);
+}
+
+static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
+{
+    stats_t stats;
+    memset(&stats, 0, sizeof(stats_t));
+    
+    load_maps(getpid(), &stats);
+
+    env->SetIntField(object, dalvikPss_field, stats.dalvikPss);
+    env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty);
+    env->SetIntField(object, dalvikSharedDirty_field, stats.dalvikSharedDirty);
+    
+    env->SetIntField(object, nativePss_field, stats.nativePss);
+    env->SetIntField(object, nativePrivateDirty_field, stats.nativePrivateDirty);
+    env->SetIntField(object, nativeSharedDirty_field, stats.nativeSharedDirty);
+    
+    env->SetIntField(object, otherPss_field, stats.otherPss);
+    env->SetIntField(object, otherPrivateDirty_field, stats.otherPrivateDirty);
+    env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty);
+}
+
+static jint read_binder_stat(const char* stat)
+{
+    FILE* fp = fopen(BINDER_STATS, "r");
+    if (fp == NULL) {
+        return -1;
+    }
+
+    char line[1024];
+
+    char compare[128];
+    int len = snprintf(compare, 128, "proc %d", getpid());
+    
+    // loop until we have the block that represents this process
+    do {
+        if (fgets(line, 1024, fp) == 0) {
+            return -1;
+        }
+    } while (strncmp(compare, line, len));
+
+    // now that we have this process, read until we find the stat that we are looking for 
+    len = snprintf(compare, 128, "  %s: ", stat);
+    
+    do {
+        if (fgets(line, 1024, fp) == 0) {
+            return -1;
+        }
+    } while (strncmp(compare, line, len));
+    
+    // we have the line, now increment the line ptr to the value
+    char* ptr = line + len;
+    return atoi(ptr);
+}
+
+static jint android_os_Debug_getBinderSentTransactions(JNIEnv *env, jobject clazz)
+{
+    return read_binder_stat("bcTRANSACTION");
+}
+
+static jint android_os_getBinderReceivedTransactions(JNIEnv *env, jobject clazz)
+{
+    return read_binder_stat("brTRANSACTION");
+}
+
+// these are implemented in android_util_Binder.cpp
+jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz);
+jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz);
+jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz);
+
+/*
+ * JNI registration.
+ */
+
+static JNINativeMethod gMethods[] = {
+    { "getNativeHeapSize",      "()J",
+            (void*) android_os_Debug_getNativeHeapSize },
+    { "getNativeHeapAllocatedSize", "()J",
+            (void*) android_os_Debug_getNativeHeapAllocatedSize },
+    { "getNativeHeapFreeSize",  "()J",
+            (void*) android_os_Debug_getNativeHeapFreeSize },
+    { "getMemoryInfo",          "(Landroid/os/Debug$MemoryInfo;)V",
+            (void*) android_os_Debug_getDirtyPages },
+    { "getBinderSentTransactions", "()I",
+            (void*) android_os_Debug_getBinderSentTransactions },
+    { "getBinderReceivedTransactions", "()I",
+            (void*) android_os_getBinderReceivedTransactions },
+    { "getBinderLocalObjectCount", "()I",
+            (void*)android_os_Debug_getLocalObjectCount },
+    { "getBinderProxyObjectCount", "()I",
+            (void*)android_os_Debug_getProxyObjectCount },
+    { "getBinderDeathObjectCount", "()I",
+            (void*)android_os_Debug_getDeathObjectCount },
+};
+
+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");
+    
+    otherPss_field = env->GetFieldID(clazz, "otherPss", "I");
+    otherPrivateDirty_field = env->GetFieldID(clazz, "otherPrivateDirty", "I");
+    otherSharedDirty_field = env->GetFieldID(clazz, "otherSharedDirty", "I");
+    
+    return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
+}
+
+};