am 1dd01130: am e2b220e8: am 0619edd3: am 7ab82a0c: am 657dbc40: am b3776881: am 8b916936: am 2e582d13: am 9bce4032: am 08ee74b1: am ea5586ef: am 4be7c61a: am 5677513b: am da37ed8b: am b9ba0c6c: Prevent authenticators from using Settings to  launch arbitrary activitie

* commit '1dd01130cd0a3a43fac14da3a998ae0ac282cf80':
  Prevent authenticators from using Settings to  launch arbitrary activities.
diff --git a/api/current.txt b/api/current.txt
index 1c24e01..db4be87 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22524,6 +22524,9 @@
   }
 
   public class Type extends android.renderscript.BaseObj {
+    method public static android.renderscript.Type createX(android.renderscript.RenderScript, android.renderscript.Element, int);
+    method public static android.renderscript.Type createXY(android.renderscript.RenderScript, android.renderscript.Element, int, int);
+    method public static android.renderscript.Type createXYZ(android.renderscript.RenderScript, android.renderscript.Element, int, int, int);
     method public int getCount();
     method public android.renderscript.Element getElement();
     method public int getX();
diff --git a/cmds/idmap/Android.mk b/cmds/idmap/Android.mk
new file mode 100644
index 0000000..ffa83f2
--- /dev/null
+++ b/cmds/idmap/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := idmap.cpp create.cpp scan.cpp inspect.cpp
+
+LOCAL_SHARED_LIBRARIES := liblog libutils libandroidfw
+
+LOCAL_MODULE := idmap
+
+LOCAL_C_INCLUDES := external/zlib
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
new file mode 100644
index 0000000..ae35f7b
--- /dev/null
+++ b/cmds/idmap/create.cpp
@@ -0,0 +1,222 @@
+#include "idmap.h"
+
+#include <UniquePtr.h>
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <androidfw/ZipFileRO.h>
+#include <utils/String8.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+using namespace android;
+
+namespace {
+    int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc)
+    {
+        UniquePtr<ZipFileRO> zip(ZipFileRO::open(zip_path));
+        if (zip.get() == NULL) {
+            return -1;
+        }
+        ZipEntryRO entry = zip->findEntryByName(entry_name);
+        if (entry == NULL) {
+            return -1;
+        }
+        if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)crc)) {
+            return -1;
+        }
+        zip->releaseEntry(entry);
+        return 0;
+    }
+
+    int open_idmap(const char *path)
+    {
+        int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644));
+        if (fd == -1) {
+            ALOGD("error: open %s: %s\n", path, strerror(errno));
+            goto fail;
+        }
+        if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
+            ALOGD("error: fchmod %s: %s\n", path, strerror(errno));
+            goto fail;
+        }
+        if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) {
+            ALOGD("error: flock %s: %s\n", path, strerror(errno));
+            goto fail;
+        }
+
+        return fd;
+fail:
+        if (fd != -1) {
+            close(fd);
+            unlink(path);
+        }
+        return -1;
+    }
+
+    int write_idmap(int fd, const uint32_t *data, size_t size)
+    {
+        if (lseek(fd, SEEK_SET, 0) < 0) {
+            return -1;
+        }
+        size_t bytesLeft = size;
+        while (bytesLeft > 0) {
+            ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft));
+            if (w < 0) {
+                fprintf(stderr, "error: write: %s\n", strerror(errno));
+                return -1;
+            }
+            bytesLeft -= w;
+        }
+        return 0;
+    }
+
+    bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd)
+    {
+        static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES;
+        struct stat st;
+        if (fstat(idmap_fd, &st) == -1) {
+            return true;
+        }
+        if (st.st_size < N) {
+            // file is empty or corrupt
+            return true;
+        }
+
+        char buf[N];
+        ssize_t bytesLeft = N;
+        if (lseek(idmap_fd, SEEK_SET, 0) < 0) {
+            return true;
+        }
+        for (;;) {
+            ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft));
+            if (r < 0) {
+                return true;
+            }
+            bytesLeft -= r;
+            if (bytesLeft == 0) {
+                break;
+            }
+            if (r == 0) {
+                // "shouldn't happen"
+                return true;
+            }
+        }
+
+        uint32_t cached_target_crc, cached_overlay_crc;
+        String8 cached_target_path, cached_overlay_path;
+        if (!ResTable::getIdmapInfo(buf, N, &cached_target_crc, &cached_overlay_crc,
+                    &cached_target_path, &cached_overlay_path)) {
+            return true;
+        }
+
+        if (cached_target_path != target_apk_path) {
+            return true;
+        }
+        if (cached_overlay_path != overlay_apk_path) {
+            return true;
+        }
+
+        uint32_t actual_target_crc, actual_overlay_crc;
+        if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
+				&actual_target_crc) == -1) {
+            return true;
+        }
+        if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
+				&actual_overlay_crc) == -1) {
+            return true;
+        }
+
+        return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc;
+    }
+
+    bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path,
+            const char *idmap_path)
+    {
+        struct stat st;
+        if (stat(idmap_path, &st) == -1) {
+            // non-existing idmap is always stale; on other errors, abort idmap generation
+            return errno == ENOENT;
+        }
+
+        int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY));
+        if (idmap_fd == -1) {
+            return false;
+        }
+        bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd);
+        close(idmap_fd);
+        return is_stale;
+    }
+
+    int create_idmap(const char *target_apk_path, const char *overlay_apk_path,
+            uint32_t **data, size_t *size)
+    {
+        uint32_t target_crc, overlay_crc;
+        if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME,
+				&target_crc) == -1) {
+            return -1;
+        }
+        if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME,
+				&overlay_crc) == -1) {
+            return -1;
+        }
+
+        AssetManager am;
+        bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc,
+                data, size);
+        return b ? 0 : -1;
+    }
+
+    int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path,
+            int fd, bool check_if_stale)
+    {
+        if (check_if_stale) {
+            if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) {
+                // already up to date -- nothing to do
+                return 0;
+            }
+        }
+
+        uint32_t *data = NULL;
+        size_t size;
+
+        if (create_idmap(target_apk_path, overlay_apk_path, &data, &size) == -1) {
+            return -1;
+        }
+
+        if (write_idmap(fd, data, size) == -1) {
+            free(data);
+            return -1;
+        }
+
+        free(data);
+        return 0;
+    }
+}
+
+int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
+        const char *idmap_path)
+{
+    if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) {
+        // already up to date -- nothing to do
+        return EXIT_SUCCESS;
+    }
+
+    int fd = open_idmap(idmap_path);
+    if (fd == -1) {
+        return EXIT_FAILURE;
+    }
+
+    int r = create_and_write_idmap(target_apk_path, overlay_apk_path, fd, false);
+    close(fd);
+    if (r != 0) {
+        unlink(idmap_path);
+    }
+    return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd)
+{
+    return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ?
+        EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp
new file mode 100644
index 0000000..46c0edc
--- /dev/null
+++ b/cmds/idmap/idmap.cpp
@@ -0,0 +1,237 @@
+#include "idmap.h"
+
+#include <private/android_filesystem_config.h> // for AID_SYSTEM
+
+#include <stdlib.h>
+#include <string.h>
+
+namespace {
+    const char *usage = "NAME\n\
+      idmap - create or display idmap files\n\
+\n\
+SYNOPSIS \n\
+      idmap --help \n\
+      idmap --fd target overlay fd \n\
+      idmap --path target overlay idmap \n\
+      idmap --scan dir-to-scan target-to-look-for target dir-to-hold-idmaps \n\
+      idmap --inspect idmap \n\
+\n\
+DESCRIPTION \n\
+      Idmap files play an integral part in the runtime resource overlay framework. An idmap \n\
+      file contains a mapping of resource identifiers between overlay package and its target \n\
+      package; this mapping is used during resource lookup. Idmap files also act as control \n\
+      files by their existence: if not present, the corresponding overlay package is ignored \n\
+      when the resource context is created. \n\
+\n\
+      Idmap files are stored in /data/resource-cache. For each pair (target package, overlay \n\
+      package), there exists exactly one idmap file, or none if the overlay should not be used. \n\
+\n\
+NOMENCLATURE \n\
+      target: the original, non-overlay, package. Each target package may be associated with \n\
+              any number of overlay packages. \n\
+\n\
+      overlay: an overlay package. Each overlay package is associated with exactly one target \n\
+               package, specified in the overlay's manifest using the <overlay target=\"...\"/> \n\
+               tag. \n\
+\n\
+OPTIONS \n\
+      --help: display this help \n\
+\n\
+      --fd: create idmap for target package 'target' (path to apk) and overlay package 'overlay' \n\
+            (path to apk); write results to file descriptor 'fd' (integer). This invocation \n\
+            version is intended to be used by a parent process with higher privileges to call \n\
+            idmap in a controlled way: the parent will open a suitable file descriptor, fork, \n\
+            drop its privileges and exec. This tool will continue execution without the extra \n\
+            privileges, but still have write access to a file it could not have opened on its \n\
+            own. \n\
+\n\
+      --path: create idmap for target package 'target' (path to apk) and overlay package \n\
+              'overlay' (path to apk); write results to 'idmap' (path). \n\
+\n\
+      --scan: non-recursively search directory 'dir-to-scan' (path) for overlay packages with \n\
+              target package 'target-to-look-for' (package name) present at 'target' (path to \n\
+              apk). For each overlay package found, create an idmap file in 'dir-to-hold-idmaps' \n\
+              (path). \n\
+\n\
+      --inspect: decode the binary format of 'idmap' (path) and display the contents in a \n\
+                 debug-friendly format. \n\
+\n\
+EXAMPLES \n\
+      Create an idmap file: \n\
+\n\
+      $ adb shell idmap --path /system/app/target.apk \\ \n\
+                               /vendor/overlay/overlay.apk \\ \n\
+                               /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\
+\n\
+      Display an idmap file: \n\
+\n\
+      $ adb shell idmap --inspect /data/resource-cache/vendor@overlay@overlay.apk@idmap \n\
+      SECTION      ENTRY        VALUE      OFFSET    COMMENT \n\
+      IDMAP HEADER magic        0x706d6469 0x0 \n\
+                   base crc     0x484aa77f 0x1 \n\
+                   overlay crc  0x03c66fa5 0x2 \n\
+                   base path    .......... 0x03-0x42 /system/app/target.apk \n\
+                   overlay path .......... 0x43-0x82 /vendor/overlay/overlay.apk \n\
+      DATA HEADER  types count  0x00000003 0x83 \n\
+                   padding      0x00000000 0x84 \n\
+                   type offset  0x00000004 0x85      absolute offset 0x87, xml \n\
+                   type offset  0x00000007 0x86      absolute offset 0x8a, string \n\
+      DATA BLOCK   entry count  0x00000001 0x87 \n\
+                   entry offset 0x00000000 0x88 \n\
+                   entry        0x7f020000 0x89      xml/integer \n\
+      DATA BLOCK   entry count  0x00000002 0x8a \n\
+                   entry offset 0x00000000 0x8b \n\
+                   entry        0x7f030000 0x8c      string/str \n\
+                   entry        0x7f030001 0x8d      string/str2 \n\
+\n\
+      In this example, the overlay package provides three alternative resource values:\n\
+      xml/integer, string/str and string/str2.\n\
+\n\
+NOTES \n\
+      This tool and its expected invocation from installd is modelled on dexopt.";
+
+    bool verify_directory_readable(const char *path)
+    {
+        return access(path, R_OK | X_OK) == 0;
+    }
+
+    bool verify_directory_writable(const char *path)
+    {
+        return access(path, W_OK) == 0;
+    }
+
+    bool verify_file_readable(const char *path)
+    {
+        return access(path, R_OK) == 0;
+    }
+
+    bool verify_root_or_system()
+    {
+        uid_t uid = getuid();
+        gid_t gid = getgid();
+
+        return (uid == 0 && gid == 0) || (uid == AID_SYSTEM && gid == AID_SYSTEM);
+    }
+
+    int maybe_create_fd(const char *target_apk_path, const char *overlay_apk_path,
+            const char *idmap_str)
+    {
+        // anyone (not just root or system) may do --fd -- the file has
+        // already been opened by someone else on our behalf
+
+        char *endptr;
+        int idmap_fd = strtol(idmap_str, &endptr, 10);
+        if (*endptr != '\0') {
+            fprintf(stderr, "error: failed to parse file descriptor argument %s\n", idmap_str);
+            return -1;
+        }
+
+        if (!verify_file_readable(target_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
+            return -1;
+        }
+
+        if (!verify_file_readable(overlay_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
+            return -1;
+        }
+
+        return idmap_create_fd(target_apk_path, overlay_apk_path, idmap_fd);
+    }
+
+    int maybe_create_path(const char *target_apk_path, const char *overlay_apk_path,
+            const char *idmap_path)
+    {
+        if (!verify_root_or_system()) {
+            fprintf(stderr, "error: permission denied: not user root or user system\n");
+            return -1;
+        }
+
+        if (!verify_file_readable(target_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
+            return -1;
+        }
+
+        if (!verify_file_readable(overlay_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
+            return -1;
+        }
+
+        return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path);
+    }
+
+    int maybe_scan(const char *overlay_dir, const char *target_package_name,
+            const char *target_apk_path, const char *idmap_dir)
+    {
+        if (!verify_root_or_system()) {
+            fprintf(stderr, "error: permission denied: not user root or user system\n");
+            return -1;
+        }
+
+        if (!verify_directory_readable(overlay_dir)) {
+            ALOGD("error: no read access to %s: %s\n", overlay_dir, strerror(errno));
+            return -1;
+        }
+
+        if (!verify_file_readable(target_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
+            return -1;
+        }
+
+        if (!verify_directory_writable(idmap_dir)) {
+            ALOGD("error: no write access to %s: %s\n", idmap_dir, strerror(errno));
+            return -1;
+        }
+
+        return idmap_scan(overlay_dir, target_package_name, target_apk_path, idmap_dir);
+    }
+
+    int maybe_inspect(const char *idmap_path)
+    {
+        // anyone (not just root or system) may do --inspect
+        if (!verify_file_readable(idmap_path)) {
+            ALOGD("error: failed to read idmap %s: %s\n", idmap_path, strerror(errno));
+            return -1;
+        }
+        return idmap_inspect(idmap_path);
+    }
+}
+
+int main(int argc, char **argv)
+{
+#if 0
+    {
+        char buf[1024];
+        buf[0] = '\0';
+        for (int i = 0; i < argc; ++i) {
+            strncat(buf, argv[i], sizeof(buf) - 1);
+            strncat(buf, " ", sizeof(buf) - 1);
+        }
+        ALOGD("%s:%d: uid=%d gid=%d argv=%s\n", __FILE__, __LINE__, getuid(), getgid(), buf);
+    }
+#endif
+
+    if (argc == 2 && !strcmp(argv[1], "--help")) {
+        printf("%s\n", usage);
+        return 0;
+    }
+
+    if (argc == 5 && !strcmp(argv[1], "--fd")) {
+        return maybe_create_fd(argv[2], argv[3], argv[4]);
+    }
+
+    if (argc == 5 && !strcmp(argv[1], "--path")) {
+        return maybe_create_path(argv[2], argv[3], argv[4]);
+    }
+
+    if (argc == 6 && !strcmp(argv[1], "--scan")) {
+        return maybe_scan(argv[2], argv[3], argv[4], argv[5]);
+    }
+
+    if (argc == 3 && !strcmp(argv[1], "--inspect")) {
+        return maybe_inspect(argv[2]);
+    }
+
+    fprintf(stderr, "Usage: don't use this (cf dexopt usage).\n");
+    return EXIT_FAILURE;
+}
diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h
new file mode 100644
index 0000000..f507dd8
--- /dev/null
+++ b/cmds/idmap/idmap.h
@@ -0,0 +1,34 @@
+#ifndef _IDMAP_H_
+#define _IDMAP_H_
+
+#define LOG_TAG "idmap"
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#ifndef TEMP_FAILURE_RETRY
+// Used to retry syscalls that can return EINTR.
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path,
+        const char *idmap_path);
+
+int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
+
+// Regarding target_package_name: the idmap_scan implementation should
+// be able to extract this from the manifest in target_apk_path,
+// simplifying the external API.
+int idmap_scan(const char *overlay_dir, const char *target_package_name,
+        const char *target_apk_path, const char *idmap_dir);
+
+int idmap_inspect(const char *idmap_path);
+
+#endif // _IDMAP_H_
diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
new file mode 100644
index 0000000..a59f5d3
--- /dev/null
+++ b/cmds/idmap/inspect.cpp
@@ -0,0 +1,291 @@
+#include "idmap.h"
+
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+using namespace android;
+
+#define NEXT(b, i, o) do { if (buf.next(&i, &o) < 0) { return -1; } } while (0)
+
+namespace {
+    static const uint32_t IDMAP_MAGIC = 0x706d6469;
+    static const size_t PATH_LENGTH = 256;
+    static const uint32_t IDMAP_HEADER_SIZE = (3 + 2 * (PATH_LENGTH / sizeof(uint32_t)));
+
+    void printe(const char *fmt, ...);
+
+    class IdmapBuffer {
+        private:
+            char *buf_;
+            size_t len_;
+            mutable size_t pos_;
+        public:
+            IdmapBuffer() : buf_((char *)MAP_FAILED), len_(0), pos_(0) {}
+
+            ~IdmapBuffer() {
+                if (buf_ != MAP_FAILED) {
+                    munmap(buf_, len_);
+                }
+            }
+
+            int init(const char *idmap_path)
+            {
+                struct stat st;
+                int fd;
+
+                if (stat(idmap_path, &st) < 0) {
+                    printe("failed to stat idmap '%s': %s\n", idmap_path, strerror(errno));
+                    return -1;
+                }
+                len_ = st.st_size;
+                if ((fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY))) < 0) {
+                    printe("failed to open idmap '%s': %s\n", idmap_path, strerror(errno));
+                    return -1;
+                }
+                if ((buf_ = (char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+                    close(fd);
+                    printe("failed to mmap idmap: %s\n", strerror(errno));
+                    return -1;
+                }
+                close(fd);
+                return 0;
+            }
+
+            int next(uint32_t *i, uint32_t *offset) const
+            {
+                if (!buf_) {
+                    printe("failed to read next uint32_t: buffer not initialized\n");
+                    return -1;
+                }
+                if (pos_ + 4 > len_) {
+                    printe("failed to read next uint32_t: end of buffer reached at pos=0x%08x\n",
+                            pos_);
+                    return -1;
+                }
+                *offset = pos_ / sizeof(uint32_t);
+                char a = buf_[pos_++];
+                char b = buf_[pos_++];
+                char c = buf_[pos_++];
+                char d = buf_[pos_++];
+                *i = (d << 24) | (c << 16) | (b << 8) | a;
+                return 0;
+            }
+
+            int nextPath(char *b, uint32_t *offset_start, uint32_t *offset_end) const
+            {
+                if (!buf_) {
+                    printe("failed to read next path: buffer not initialized\n");
+                    return -1;
+                }
+                if (pos_ + PATH_LENGTH > len_) {
+                    printe("failed to read next path: end of buffer reached at pos=0x%08x\n", pos_);
+                    return -1;
+                }
+                memcpy(b, buf_ + pos_, PATH_LENGTH);
+                *offset_start = pos_ / sizeof(uint32_t);
+                pos_ += PATH_LENGTH;
+                *offset_end = pos_ / sizeof(uint32_t) - 1;
+                return 0;
+            }
+    };
+
+    void printe(const char *fmt, ...)
+    {
+        va_list ap;
+
+        va_start(ap, fmt);
+        fprintf(stderr, "error: ");
+        vfprintf(stderr, fmt, ap);
+        va_end(ap);
+    }
+
+    void print_header()
+    {
+        printf("SECTION      ENTRY        VALUE      OFFSET    COMMENT\n");
+    }
+
+    void print(const char *section, const char *subsection, uint32_t value, uint32_t offset,
+            const char *fmt, ...)
+    {
+        va_list ap;
+
+        va_start(ap, fmt);
+        printf("%-12s %-12s 0x%08x 0x%-4x    ", section, subsection, value, offset);
+        vprintf(fmt, ap);
+        printf("\n");
+        va_end(ap);
+    }
+
+    void print_path(const char *section, const char *subsection, uint32_t offset_start,
+            uint32_t offset_end, const char *fmt, ...)
+    {
+        va_list ap;
+
+        va_start(ap, fmt);
+        printf("%-12s %-12s .......... 0x%02x-0x%02x ", section, subsection, offset_start,
+                offset_end);
+        vprintf(fmt, ap);
+        printf("\n");
+        va_end(ap);
+    }
+
+    int resource_metadata(const AssetManager& am, uint32_t res_id,
+            String8 *package, String8 *type, String8 *name)
+    {
+        const ResTable& rt = am.getResources();
+        struct ResTable::resource_name data;
+        if (!rt.getResourceName(res_id, false, &data)) {
+            printe("failed to get resource name id=0x%08x\n", res_id);
+            return -1;
+        }
+        if (package) {
+            *package = String8(String16(data.package, data.packageLen));
+        }
+        if (type) {
+            *type = String8(String16(data.type, data.typeLen));
+        }
+        if (name) {
+            *name = String8(String16(data.name, data.nameLen));
+        }
+        return 0;
+    }
+
+    int package_id(const AssetManager& am)
+    {
+        return (am.getResources().getBasePackageId(0)) << 24;
+    }
+
+    int parse_idmap_header(const IdmapBuffer& buf, AssetManager& am)
+    {
+        uint32_t i, o, e;
+        char path[PATH_LENGTH];
+
+        NEXT(buf, i, o);
+        if (i != IDMAP_MAGIC) {
+            printe("not an idmap file: actual magic constant 0x%08x does not match expected magic "
+                    "constant 0x%08x\n", i, IDMAP_MAGIC);
+            return -1;
+        }
+        print_header();
+        print("IDMAP HEADER", "magic", i, o, "");
+
+        NEXT(buf, i, o);
+        print("", "base crc", i, o, "");
+
+        NEXT(buf, i, o);
+        print("", "overlay crc", i, o, "");
+
+        if (buf.nextPath(path, &o, &e) < 0) {
+            // printe done from IdmapBuffer::nextPath
+            return -1;
+        }
+        print_path("", "base path", o, e, "%s", path);
+        if (!am.addAssetPath(String8(path), NULL)) {
+            printe("failed to add '%s' as asset path\n", path);
+            return -1;
+        }
+
+        if (buf.nextPath(path, &o, &e) < 0) {
+            // printe done from IdmapBuffer::nextPath
+            return -1;
+        }
+        print_path("", "overlay path", o, e, "%s", path);
+
+        return 0;
+    }
+
+    int parse_data_header(const IdmapBuffer& buf, const AssetManager& am, Vector<uint32_t>& types)
+    {
+        uint32_t i, o;
+        const uint32_t numeric_package = package_id(am);
+
+        NEXT(buf, i, o);
+        print("DATA HEADER", "types count", i, o, "");
+        const uint32_t N = i;
+
+        for (uint32_t j = 0; j < N; ++j) {
+            NEXT(buf, i, o);
+            if (i == 0) {
+                print("", "padding", i, o, "");
+            } else {
+                String8 type;
+                const uint32_t numeric_type = (j + 1) << 16;
+                const uint32_t res_id = numeric_package | numeric_type;
+                if (resource_metadata(am, res_id, NULL, &type, NULL) < 0) {
+                    // printe done from resource_metadata
+                    return -1;
+                }
+                print("", "type offset", i, o, "absolute offset 0x%02x, %s",
+                        i + IDMAP_HEADER_SIZE, type.string());
+                types.add(numeric_type);
+            }
+        }
+
+        return 0;
+    }
+
+    int parse_data_block(const IdmapBuffer& buf, const AssetManager& am, size_t numeric_type)
+    {
+        uint32_t i, o, n, id_offset;
+        const uint32_t numeric_package = package_id(am);
+
+        NEXT(buf, i, o);
+        print("DATA BLOCK", "entry count", i, o, "");
+        n = i;
+
+        NEXT(buf, i, o);
+        print("", "entry offset", i, o, "");
+        id_offset = i;
+
+        for ( ; n > 0; --n) {
+            String8 type, name;
+
+            NEXT(buf, i, o);
+            if (i == 0) {
+                print("", "padding", i, o, "");
+            } else {
+                uint32_t res_id = numeric_package | numeric_type | id_offset;
+                if (resource_metadata(am, res_id, NULL, &type, &name) < 0) {
+                    // printe done from resource_metadata
+                    return -1;
+                }
+                print("", "entry", i, o, "%s/%s", type.string(), name.string());
+            }
+            ++id_offset;
+        }
+
+        return 0;
+    }
+}
+
+int idmap_inspect(const char *idmap_path)
+{
+    IdmapBuffer buf;
+    if (buf.init(idmap_path) < 0) {
+        // printe done from IdmapBuffer::init
+        return EXIT_FAILURE;
+    }
+    AssetManager am;
+    if (parse_idmap_header(buf, am) < 0) {
+        // printe done from parse_idmap_header
+        return EXIT_FAILURE;
+    }
+    Vector<uint32_t> types;
+    if (parse_data_header(buf, am, types) < 0) {
+        // printe done from parse_data_header
+        return EXIT_FAILURE;
+    }
+    const size_t N = types.size();
+    for (size_t i = 0; i < N; ++i) {
+        if (parse_data_block(buf, am, types.itemAt(i)) < 0) {
+            // printe done from parse_data_block
+            return EXIT_FAILURE;
+        }
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
new file mode 100644
index 0000000..c5fc941
--- /dev/null
+++ b/cmds/idmap/scan.cpp
@@ -0,0 +1,244 @@
+#include "idmap.h"
+
+#include <UniquePtr.h>
+#include <androidfw/ResourceTypes.h>
+#include <androidfw/StreamingZipInflater.h>
+#include <androidfw/ZipFileRO.h>
+#include <private/android_filesystem_config.h> // for AID_SYSTEM
+#include <utils/SortedVector.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+#include <dirent.h>
+
+#define NO_OVERLAY_TAG (-1000)
+
+using namespace android;
+
+namespace {
+    struct Overlay {
+        Overlay() {}
+        Overlay(const String8& a, const String8& i, int p) :
+            apk_path(a), idmap_path(i), priority(p) {}
+
+        bool operator<(Overlay const& rhs) const
+        {
+            // Note: order is reversed by design
+            return rhs.priority < priority;
+        }
+
+        String8 apk_path;
+        String8 idmap_path;
+        int priority;
+    };
+
+    bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector)
+    {
+        FILE* fout = fopen(filename, "w");
+        if (fout == NULL) {
+            return false;
+        }
+
+        for (size_t i = 0; i < overlayVector.size(); ++i) {
+            const Overlay& overlay = overlayVector[i];
+            fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string());
+        }
+
+        fclose(fout);
+
+        // Make file world readable since Zygote (running as root) will read
+        // it when creating the initial AssetManger object
+        const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
+        if (chmod(filename, mode) == -1) {
+            unlink(filename);
+            return false;
+        }
+
+        return true;
+    }
+
+    String8 flatten_path(const char *path)
+    {
+        String16 tmp(path);
+        tmp.replaceAll('/', '@');
+        return String8(tmp);
+    }
+
+    int mkdir_p(const String8& path, uid_t uid, gid_t gid)
+    {
+        static const mode_t mode =
+            S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH;
+        struct stat st;
+
+        if (stat(path.string(), &st) == 0) {
+            return 0;
+        }
+        if (mkdir_p(path.getPathDir(), uid, gid) < 0) {
+            return -1;
+        }
+        if (mkdir(path.string(), 0755) != 0) {
+            return -1;
+        }
+        if (chown(path.string(), uid, gid) == -1) {
+            return -1;
+        }
+        if (chmod(path.string(), mode) == -1) {
+            return -1;
+        }
+        return 0;
+    }
+
+    int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name)
+    {
+        const size_t N = parser.getAttributeCount();
+        String16 target;
+        int priority = -1;
+        for (size_t i = 0; i < N; ++i) {
+            size_t len;
+            String16 key(parser.getAttributeName(i, &len));
+            if (key == String16("targetPackage")) {
+                const uint16_t *p = parser.getAttributeStringValue(i, &len);
+                if (p) {
+                    target = String16(p, len);
+                }
+            } else if (key == String16("priority")) {
+                Res_value v;
+                if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
+                    priority = v.data;
+                    if (priority < 0 || priority > 9999) {
+                        return -1;
+                    }
+                }
+            }
+        }
+        if (target == String16(target_package_name)) {
+            return priority;
+        }
+        return NO_OVERLAY_TAG;
+    }
+
+    int parse_manifest(const void *data, size_t size, const char *target_package_name)
+    {
+        ResXMLTree parser(data, size);
+        if (parser.getError() != NO_ERROR) {
+            ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
+            return -1;
+        }
+
+        ResXMLParser::event_code_t type;
+        do {
+            type = parser.next();
+            if (type == ResXMLParser::START_TAG) {
+                size_t len;
+                String16 tag(parser.getElementName(&len));
+                if (tag == String16("overlay")) {
+                    return parse_overlay_tag(parser, target_package_name);
+                }
+            }
+        } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
+
+        return NO_OVERLAY_TAG;
+    }
+
+    int parse_apk(const char *path, const char *target_package_name)
+    {
+        UniquePtr<ZipFileRO> zip(ZipFileRO::open(path));
+        if (zip.get() == NULL) {
+            ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path);
+            return -1;
+        }
+        ZipEntryRO entry;
+        if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) {
+            ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__);
+            return -1;
+        }
+        size_t uncompLen = 0;
+        int method;
+        if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) {
+            ALOGW("%s: failed to read entry info\n", __FUNCTION__);
+            return -1;
+        }
+        if (method != ZipFileRO::kCompressDeflated) {
+            ALOGW("%s: cannot handle zip compression method %d\n", __FUNCTION__, method);
+            return -1;
+        }
+        FileMap *dataMap = zip->createEntryFileMap(entry);
+        if (!dataMap) {
+            ALOGW("%s: failed to create FileMap\n", __FUNCTION__);
+            return -1;
+        }
+        char *buf = new char[uncompLen];
+        if (NULL == buf) {
+            ALOGW("%s: failed to allocate %d byte\n", __FUNCTION__, uncompLen);
+            dataMap->release();
+            return -1;
+        }
+        StreamingZipInflater inflater(dataMap, uncompLen);
+        if (inflater.read(buf, uncompLen) < 0) {
+            ALOGW("%s: failed to inflate %d byte\n", __FUNCTION__, uncompLen);
+            delete[] buf;
+            dataMap->release();
+            return -1;
+        }
+
+        int priority = parse_manifest(buf, uncompLen, target_package_name);
+        delete[] buf;
+        dataMap->release();
+        return priority;
+    }
+}
+
+int idmap_scan(const char *overlay_dir, const char *target_package_name,
+        const char *target_apk_path, const char *idmap_dir)
+{
+    String8 filename = String8(idmap_dir);
+    filename.appendPath("overlays.list");
+    if (unlink(filename.string()) != 0 && errno != ENOENT) {
+        return EXIT_FAILURE;
+    }
+
+    DIR *dir = opendir(overlay_dir);
+    if (dir == NULL) {
+        return EXIT_FAILURE;
+    }
+
+    SortedVector<Overlay> overlayVector;
+    struct dirent *dirent;
+    while ((dirent = readdir(dir)) != NULL) {
+        struct stat st;
+        char overlay_apk_path[PATH_MAX + 1];
+        snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
+        if (stat(overlay_apk_path, &st) < 0) {
+            continue;
+        }
+        if (!S_ISREG(st.st_mode)) {
+            continue;
+        }
+
+        int priority = parse_apk(overlay_apk_path, target_package_name);
+        if (priority < 0) {
+            continue;
+        }
+
+        String8 idmap_path(idmap_dir);
+        idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
+        idmap_path.append("@idmap");
+
+        if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
+            ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
+                    target_apk_path, overlay_apk_path, idmap_path.string());
+            continue;
+        }
+
+        Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
+        overlayVector.add(overlay);
+    }
+
+    closedir(dir);
+
+    if (!writePackagesList(filename.string(), overlayVector)) {
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 43014ad..21f6eda 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -743,9 +743,9 @@
     static class IntPropertyValuesHolder extends PropertyValuesHolder {
 
         // Cache JNI functions to avoid looking them up twice
-        private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap =
-                new HashMap<Class, HashMap<String, Integer>>();
-        int mJniSetter;
+        private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap =
+                new HashMap<Class, HashMap<String, Long>>();
+        long mJniSetter;
         private IntProperty mIntProperty;
 
         IntKeyframeSet mIntKeyframeSet;
@@ -845,11 +845,11 @@
             // Check new static hashmap<propName, int> for setter method
             try {
                 mPropertyMapLock.writeLock().lock();
-                HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass);
+                HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass);
                 if (propertyMap != null) {
-                    Integer mJniSetterInteger = propertyMap.get(mPropertyName);
-                    if (mJniSetterInteger != null) {
-                        mJniSetter = mJniSetterInteger;
+                    Long jniSetter = propertyMap.get(mPropertyName);
+                    if (jniSetter != null) {
+                        mJniSetter = jniSetter;
                     }
                 }
                 if (mJniSetter == 0) {
@@ -857,7 +857,7 @@
                     mJniSetter = nGetIntMethod(targetClass, methodName);
                     if (mJniSetter != 0) {
                         if (propertyMap == null) {
-                            propertyMap = new HashMap<String, Integer>();
+                            propertyMap = new HashMap<String, Long>();
                             sJNISetterPropertyMap.put(targetClass, propertyMap);
                         }
                         propertyMap.put(mPropertyName, mJniSetter);
@@ -880,9 +880,9 @@
     static class FloatPropertyValuesHolder extends PropertyValuesHolder {
 
         // Cache JNI functions to avoid looking them up twice
-        private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap =
-                new HashMap<Class, HashMap<String, Integer>>();
-        int mJniSetter;
+        private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap =
+                new HashMap<Class, HashMap<String, Long>>();
+        long mJniSetter;
         private FloatProperty mFloatProperty;
 
         FloatKeyframeSet mFloatKeyframeSet;
@@ -982,11 +982,11 @@
             // Check new static hashmap<propName, int> for setter method
             try {
                 mPropertyMapLock.writeLock().lock();
-                HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass);
+                HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass);
                 if (propertyMap != null) {
-                    Integer mJniSetterInteger = propertyMap.get(mPropertyName);
-                    if (mJniSetterInteger != null) {
-                        mJniSetter = mJniSetterInteger;
+                    Long jniSetter = propertyMap.get(mPropertyName);
+                    if (jniSetter != null) {
+                        mJniSetter = jniSetter;
                     }
                 }
                 if (mJniSetter == 0) {
@@ -994,7 +994,7 @@
                     mJniSetter = nGetFloatMethod(targetClass, methodName);
                     if (mJniSetter != 0) {
                         if (propertyMap == null) {
-                            propertyMap = new HashMap<String, Integer>();
+                            propertyMap = new HashMap<String, Long>();
                             sJNISetterPropertyMap.put(targetClass, propertyMap);
                         }
                         propertyMap.put(mPropertyName, mJniSetter);
@@ -1015,8 +1015,8 @@
 
     }
 
-    native static private int nGetIntMethod(Class targetClass, String methodName);
-    native static private int nGetFloatMethod(Class targetClass, String methodName);
-    native static private void nCallIntMethod(Object target, int methodID, int arg);
-    native static private void nCallFloatMethod(Object target, int methodID, float arg);
-}
\ No newline at end of file
+    native static private long nGetIntMethod(Class targetClass, String methodName);
+    native static private long nGetFloatMethod(Class targetClass, String methodName);
+    native static private void nCallIntMethod(Object target, long methodID, int arg);
+    native static private void nCallFloatMethod(Object target, long methodID, float arg);
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d6db8c2..10ef535 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -816,7 +816,7 @@
     }
 
     /**
-     * Return the LoaderManager for this fragment, creating it if needed.
+     * Return the LoaderManager for this activity, creating it if needed.
      */
     public LoaderManager getLoaderManager() {
         if (mLoaderManager != null) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9f21a36..4b86b0c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1541,11 +1541,11 @@
     /**
      * Creates the top level resources for the given package.
      */
-    Resources getTopLevelResources(String resDir,
+    Resources getTopLevelResources(String resDir, String[] overlayDirs,
             int displayId, Configuration overrideConfiguration,
             LoadedApk pkgInfo) {
-        return mResourcesManager.getTopLevelResources(resDir, displayId, overrideConfiguration,
-                pkgInfo.getCompatibilityInfo(), null);
+        return mResourcesManager.getTopLevelResources(resDir, overlayDirs, displayId,
+                overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
     }
 
     final Handler getHandler() {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index b505d4f..a280448 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -774,7 +774,7 @@
         }
         Resources r = mContext.mMainThread.getTopLevelResources(
                 app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir,
-                        Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
+                app.resourceDirs, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
         if (r != null) {
             return r;
         }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 190ddb4..8d127c6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1911,8 +1911,8 @@
         ContextImpl c = new ContextImpl();
         c.init(mPackageInfo, null, mMainThread);
         c.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
-                getDisplayId(), overrideConfiguration, mResources.getCompatibilityInfo(),
-                mActivityToken);
+                mPackageInfo.getOverlayDirs(), getDisplayId(), overrideConfiguration,
+                mResources.getCompatibilityInfo(), mActivityToken);
         return c;
     }
 
@@ -1929,7 +1929,7 @@
         context.mDisplay = display;
         DisplayAdjustments daj = getDisplayAdjustments(displayId);
         context.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
-                displayId, null, daj.getCompatibilityInfo(), null);
+                mPackageInfo.getOverlayDirs(), displayId, null, daj.getCompatibilityInfo(), null);
         return context;
     }
 
@@ -2041,7 +2041,8 @@
             mDisplayAdjustments.setCompatibilityInfo(compatInfo);
             mDisplayAdjustments.setActivityToken(activityToken);
             mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
-                    Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
+                    mPackageInfo.getOverlayDirs(), Display.DEFAULT_DISPLAY, null, compatInfo,
+                    activityToken);
         } else {
             mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
             mDisplayAdjustments.setActivityToken(activityToken);
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 8476609..ef9f26e 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -28,7 +28,7 @@
 	/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
     void set(int type, long triggerAtTime, long windowLength,
             long interval, in PendingIntent operation, in WorkSource workSource);
-    void setTime(long millis);
+    boolean setTime(long millis);
     void setTimeZone(String zone);
     void remove(in PendingIntent operation);
 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 4239a5d..0115d1b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -76,6 +76,7 @@
     final String mPackageName;
     private final String mAppDir;
     private final String mResDir;
+    private final String[] mOverlayDirs;
     private final String[] mSharedLibraries;
     private final String mDataDir;
     private final String mLibDir;
@@ -120,6 +121,7 @@
         final int myUid = Process.myUid();
         mResDir = aInfo.uid == myUid ? aInfo.sourceDir
                 : aInfo.publicSourceDir;
+        mOverlayDirs = aInfo.resourceDirs;
         if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
             aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
                     mPackageName);
@@ -159,6 +161,7 @@
         mPackageName = name;
         mAppDir = null;
         mResDir = null;
+        mOverlayDirs = null;
         mSharedLibraries = null;
         mDataDir = null;
         mDataDirFile = null;
@@ -471,6 +474,10 @@
         return mResDir;
     }
 
+    public String[] getOverlayDirs() {
+        return mOverlayDirs;
+    }
+
     public String getDataDir() {
         return mDataDir;
     }
@@ -485,7 +492,7 @@
 
     public Resources getResources(ActivityThread mainThread) {
         if (mResources == null) {
-            mResources = mainThread.getTopLevelResources(mResDir,
+            mResources = mainThread.getTopLevelResources(mResDir, mOverlayDirs,
                     Display.DEFAULT_DISPLAY, null, this);
         }
         return mResources;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index f55dba4..728f372 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -147,7 +147,7 @@
      * @param compatInfo the compability info. Must not be null.
      * @param token the application token for determining stack bounds.
      */
-    public Resources getTopLevelResources(String resDir, int displayId,
+    public Resources getTopLevelResources(String resDir, String[] overlayDirs, int displayId,
             Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
         final float scale = compatInfo.applicationScale;
         ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
@@ -180,6 +180,12 @@
             return null;
         }
 
+        if (overlayDirs != null) {
+            for (String idmapPath : overlayDirs) {
+                assets.addOverlayPath(idmapPath);
+            }
+        }
+
         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
         DisplayMetrics dm = getDisplayMetricsLocked(displayId);
         Configuration config;
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 911e49c..a045b3a 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -24,7 +24,7 @@
 import java.io.PrintWriter;
 
 /**
- * An abstract class that performs asynchronous loading of data. While Loaders are active
+ * A class that performs asynchronous loading of data. While Loaders are active
  * they should monitor the source of their data and deliver new results when the contents
  * change.  See {@link android.app.LoaderManager} for more detail.
  *
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index af1a6d5..785f2b4 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -227,6 +227,14 @@
     /** @hide */
     public String requiredAccountType;
 
+    /**
+     * What package, if any, this package will overlay.
+     *
+     * Package name of target package, or null.
+     * @hide
+     */
+    public String overlayTarget;
+
     public PackageInfo() {
     }
 
@@ -270,6 +278,7 @@
         dest.writeInt(requiredForAllUsers ? 1 : 0);
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
+        dest.writeString(overlayTarget);
     }
 
     public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -311,5 +320,6 @@
         requiredForAllUsers = source.readInt() != 0;
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
+        overlayTarget = source.readString();
     }
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4607902..52564eb 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -307,6 +307,7 @@
         }
         pi.restrictedAccountType = p.mRestrictedAccountType;
         pi.requiredAccountType = p.mRequiredAccountType;
+        pi.overlayTarget = p.mOverlayTarget;
         pi.firstInstallTime = firstInstallTime;
         pi.lastUpdateTime = lastUpdateTime;
         if ((flags&PackageManager.GET_GIDS) != 0) {
@@ -490,6 +491,11 @@
 
     public Package parsePackage(File sourceFile, String destCodePath,
             DisplayMetrics metrics, int flags) {
+        return parsePackage(sourceFile, destCodePath, metrics, flags, false);
+    }
+
+    public Package parsePackage(File sourceFile, String destCodePath,
+            DisplayMetrics metrics, int flags, boolean trustedOverlay) {
         mParseError = PackageManager.INSTALL_SUCCEEDED;
 
         mArchiveSourcePath = sourceFile.getPath();
@@ -542,7 +548,7 @@
         Exception errorException = null;
         try {
             // XXXX todo: need to figure out correct configuration.
-            pkg = parsePackage(res, parser, flags, errorText);
+            pkg = parsePackage(res, parser, flags, trustedOverlay, errorText);
         } catch (Exception e) {
             errorException = e;
             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
@@ -951,8 +957,8 @@
     }
 
     private Package parsePackage(
-        Resources res, XmlResourceParser parser, int flags, String[] outError)
-        throws XmlPullParserException, IOException {
+        Resources res, XmlResourceParser parser, int flags, boolean trustedOverlay,
+        String[] outError) throws XmlPullParserException, IOException {
         AttributeSet attrs = parser;
 
         mParseInstrumentationArgs = null;
@@ -1051,6 +1057,31 @@
                 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
                     return null;
                 }
+            } else if (tagName.equals("overlay")) {
+                pkg.mTrustedOverlay = trustedOverlay;
+
+                sa = res.obtainAttributes(attrs,
+                        com.android.internal.R.styleable.AndroidManifestResourceOverlay);
+                pkg.mOverlayTarget = sa.getString(
+                        com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
+                pkg.mOverlayPriority = sa.getInt(
+                        com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
+                        -1);
+                sa.recycle();
+
+                if (pkg.mOverlayTarget == null) {
+                    outError[0] = "<overlay> does not specify a target package";
+                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+                    return null;
+                }
+                if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
+                    outError[0] = "<overlay> priority must be between 0 and 9999";
+                    mParseError =
+                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+                    return null;
+                }
+                XmlUtils.skipCurrentTag(parser);
+
             } else if (tagName.equals("keys")) {
                 if (!parseKeys(pkg, res, parser, attrs, outError)) {
                     return null;
@@ -3546,6 +3577,10 @@
          */
         public ManifestDigest manifestDigest;
 
+        public String mOverlayTarget;
+        public int mOverlayPriority;
+        public boolean mTrustedOverlay;
+
         /**
          * Data used to feed the KeySetManager
          */
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 93ce633..9ce17e4 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -69,13 +69,13 @@
     private final long[] mOffsets = new long[2];
     
     // For communication with native code.
-    private int mObject;
+    private long mObject;
 
     private StringBlock mStringBlocks[] = null;
     
     private int mNumRefs = 1;
     private boolean mOpen = true;
-    private HashMap<Integer, RuntimeException> mRefStacks; 
+    private HashMap<Long, RuntimeException> mRefStacks;
  
     /**
      * Create a new AssetManager containing only the basic system assets.
@@ -90,7 +90,7 @@
                 mNumRefs = 0;
                 incRefsLocked(this.hashCode());
             }
-            init();
+            init(false);
             if (localLOGV) Log.v(TAG, "New asset manager: " + this);
             ensureSystemAssets();
         }
@@ -113,7 +113,7 @@
                 incRefsLocked(this.hashCode());
             }
         }
-        init();
+        init(true);
         if (localLOGV) Log.v(TAG, "New asset manager: " + this);
     }
 
@@ -224,7 +224,7 @@
         return retArray;
     }
     
-    /*package*/ final boolean getThemeValue(int theme, int ident,
+    /*package*/ final boolean getThemeValue(long theme, int ident,
             TypedValue outValue, boolean resolveRefs) {
         int block = loadThemeAttributeValue(theme, ident, outValue, resolveRefs);
         if (block >= 0) {
@@ -312,7 +312,7 @@
             if (!mOpen) {
                 throw new RuntimeException("Assetmanager has been closed");
             }
-            int asset = openAsset(fileName, accessMode);
+            long asset = openAsset(fileName, accessMode);
             if (asset != 0) {
                 AssetInputStream res = new AssetInputStream(asset);
                 incRefsLocked(res.hashCode());
@@ -404,7 +404,7 @@
             if (!mOpen) {
                 throw new RuntimeException("Assetmanager has been closed");
             }
-            int asset = openNonAssetNative(cookie, fileName, accessMode);
+            long asset = openNonAssetNative(cookie, fileName, accessMode);
             if (asset != 0) {
                 AssetInputStream res = new AssetInputStream(asset);
                 incRefsLocked(res.hashCode());
@@ -484,7 +484,7 @@
             if (!mOpen) {
                 throw new RuntimeException("Assetmanager has been closed");
             }
-            int xmlBlock = openXmlAssetNative(cookie, fileName);
+            long xmlBlock = openXmlAssetNative(cookie, fileName);
             if (xmlBlock != 0) {
                 XmlBlock res = new XmlBlock(this, xmlBlock);
                 incRefsLocked(res.hashCode());
@@ -500,18 +500,18 @@
         }
     }
 
-    /*package*/ final int createTheme() {
+    /*package*/ final long createTheme() {
         synchronized (this) {
             if (!mOpen) {
                 throw new RuntimeException("Assetmanager has been closed");
             }
-            int res = newTheme();
+            long res = newTheme();
             incRefsLocked(res);
             return res;
         }
     }
 
-    /*package*/ final void releaseTheme(int theme) {
+    /*package*/ final void releaseTheme(long theme) {
         synchronized (this) {
             deleteTheme(theme);
             decRefsLocked(theme);
@@ -537,7 +537,7 @@
     
     public final class AssetInputStream extends InputStream {
         public final int getAssetInt() {
-            return mAsset;
+            throw new UnsupportedOperationException();
         }
         /**
          * @hide
@@ -545,7 +545,7 @@
         public final long getNativeAsset() {
             return mAsset;
         }
-        private AssetInputStream(int asset)
+        private AssetInputStream(long asset)
         {
             mAsset = asset;
             mLength = getAssetLength(asset);
@@ -597,7 +597,7 @@
             close();
         }
 
-        private int mAsset;
+        private long mAsset;
         private long mLength;
         private long mMarkPos;
     }
@@ -615,6 +615,16 @@
 
     private native final int addAssetPathNative(String path);
 
+     /**
+     * Add a set of assets to overlay an already added set of assets.
+     *
+     * This is only intended for application resources. System wide resources
+     * are handled before any Java code is executed.
+     *
+     * {@hide}
+     */
+    public native final int addOverlayPath(String idmapPath);
+
     /**
      * Add multiple sets of assets to the asset manager at once.  See
      * {@link #addAssetPath(String)} for more information.  Returns array of
@@ -678,19 +688,19 @@
     /*package*/ native final String getResourceTypeName(int resid);
     /*package*/ native final String getResourceEntryName(int resid);
     
-    private native final int openAsset(String fileName, int accessMode);
+    private native final long openAsset(String fileName, int accessMode);
     private final native ParcelFileDescriptor openAssetFd(String fileName,
             long[] outOffsets) throws IOException;
-    private native final int openNonAssetNative(int cookie, String fileName,
+    private native final long openNonAssetNative(int cookie, String fileName,
             int accessMode);
     private native ParcelFileDescriptor openNonAssetFdNative(int cookie,
             String fileName, long[] outOffsets) throws IOException;
-    private native final void destroyAsset(int asset);
-    private native final int readAssetChar(int asset);
-    private native final int readAsset(int asset, byte[] b, int off, int len);
-    private native final long seekAsset(int asset, long offset, int whence);
-    private native final long getAssetLength(int asset);
-    private native final long getAssetRemainingLength(int asset);
+    private native final void destroyAsset(long asset);
+    private native final int readAssetChar(long asset);
+    private native final int readAsset(long asset, byte[] b, int off, int len);
+    private native final long seekAsset(long asset, long offset, int whence);
+    private native final long getAssetLength(long asset);
+    private native final long getAssetRemainingLength(long asset);
 
     /** Returns true if the resource was found, filling in mRetStringBlock and
      *  mRetData. */
@@ -707,15 +717,15 @@
     /*package*/ static final int STYLE_RESOURCE_ID = 3;
     /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
     /*package*/ static final int STYLE_DENSITY = 5;
-    /*package*/ native static final boolean applyStyle(int theme,
-            int defStyleAttr, int defStyleRes, int xmlParser,
+    /*package*/ native static final boolean applyStyle(long theme,
+            int defStyleAttr, int defStyleRes, long xmlParser,
             int[] inAttrs, int[] outValues, int[] outIndices);
     /*package*/ native final boolean retrieveAttributes(
-            int xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
+            long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
     /*package*/ native final int getArraySize(int resource);
     /*package*/ native final int retrieveArray(int resource, int[] outValues);
     private native final int getStringBlockCount();
-    private native final int getNativeStringBlock(int block);
+    private native final long getNativeStringBlock(int block);
 
     /**
      * {@hide}
@@ -737,37 +747,37 @@
      */
     public native static final int getGlobalAssetManagerCount();
     
-    private native final int newTheme();
-    private native final void deleteTheme(int theme);
-    /*package*/ native static final void applyThemeStyle(int theme, int styleRes, boolean force);
-    /*package*/ native static final void copyTheme(int dest, int source);
-    /*package*/ native static final int loadThemeAttributeValue(int theme, int ident,
+    private native final long newTheme();
+    private native final void deleteTheme(long theme);
+    /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
+    /*package*/ native static final void copyTheme(long dest, long source);
+    /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
                                                                 TypedValue outValue,
                                                                 boolean resolve);
-    /*package*/ native static final void dumpTheme(int theme, int priority, String tag, String prefix);
+    /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
 
-    private native final int openXmlAssetNative(int cookie, String fileName);
+    private native final long openXmlAssetNative(int cookie, String fileName);
 
     private native final String[] getArrayStringResource(int arrayRes);
     private native final int[] getArrayStringInfo(int arrayRes);
     /*package*/ native final int[] getArrayIntResource(int arrayRes);
 
-    private native final void init();
+    private native final void init(boolean isSystem);
     private native final void destroy();
 
-    private final void incRefsLocked(int id) {
+    private final void incRefsLocked(long id) {
         if (DEBUG_REFS) {
             if (mRefStacks == null) {
-                mRefStacks = new HashMap<Integer, RuntimeException>();
-                RuntimeException ex = new RuntimeException();
-                ex.fillInStackTrace();
-                mRefStacks.put(this.hashCode(), ex);
+                mRefStacks = new HashMap<Long, RuntimeException>();
             }
+            RuntimeException ex = new RuntimeException();
+            ex.fillInStackTrace();
+            mRefStacks.put(id, ex);
         }
         mNumRefs++;
     }
     
-    private final void decRefsLocked(int id) {
+    private final void decRefsLocked(long id) {
         if (DEBUG_REFS && mRefStacks != null) {
             mRefStacks.remove(id);
         }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index cd5b5d2f..3d9daca 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1460,7 +1460,7 @@
         }
 
         private final AssetManager mAssets;
-        private final int mTheme;
+        private final long mTheme;
     }
 
     /**
@@ -1569,10 +1569,7 @@
 
             String locale = null;
             if (mConfiguration.locale != null) {
-                locale = mConfiguration.locale.getLanguage();
-                if (mConfiguration.locale.getCountry() != null) {
-                    locale += "-" + mConfiguration.locale.getCountry();
-                }
+                locale = mConfiguration.locale.toLanguageTag();
             }
             int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index 78180b1..77b8a33 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -36,7 +36,7 @@
     private static final String TAG = "AssetManager";
     private static final boolean localLOGV = false;
 
-    private final int mNative;
+    private final long mNative;
     private final boolean mUseSparse;
     private final boolean mOwnsNative;
     private CharSequence[] mStrings;
@@ -474,7 +474,7 @@
      *  are doing!  The given native object must exist for the entire lifetime
      *  of this newly creating StringBlock.
      */
-    StringBlock(int obj, boolean useSparse) {
+    StringBlock(long obj, boolean useSparse) {
         mNative = obj;
         mUseSparse = useSparse;
         mOwnsNative = false;
@@ -482,11 +482,11 @@
                 + ": " + nativeGetSize(mNative));
     }
 
-    private static native int nativeCreate(byte[] data,
+    private static native long nativeCreate(byte[] data,
                                                  int offset,
                                                  int size);
-    private static native int nativeGetSize(int obj);
-    private static native String nativeGetString(int obj, int idx);
-    private static native int[] nativeGetStyle(int obj, int idx);
-    private static native void nativeDestroy(int obj);
+    private static native int nativeGetSize(long obj);
+    private static native String nativeGetString(long obj, int idx);
+    private static native int[] nativeGetStyle(long obj, int idx);
+    private static native void nativeDestroy(long obj);
 }
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index bea6529..3ad357f2 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -75,7 +75,7 @@
     }
 
     /*package*/ final class Parser implements XmlResourceParser {
-        Parser(int parseState, XmlBlock block) {
+        Parser(long parseState, XmlBlock block) {
             mParseState = parseState;
             mBlock = block;
             block.mOpenCount++;
@@ -458,7 +458,7 @@
             return mStrings.get(id);
         }
 
-        /*package*/ int mParseState;
+        /*package*/ long mParseState;
         private final XmlBlock mBlock;
         private boolean mStarted = false;
         private boolean mDecNextDepth = false;
@@ -476,41 +476,41 @@
      *  are doing!  The given native object must exist for the entire lifetime
      *  of this newly creating XmlBlock.
      */
-    XmlBlock(AssetManager assets, int xmlBlock) {
+    XmlBlock(AssetManager assets, long xmlBlock) {
         mAssets = assets;
         mNative = xmlBlock;
         mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false);
     }
 
     private final AssetManager mAssets;
-    private final int mNative;
+    private final long mNative;
     /*package*/ final StringBlock mStrings;
     private boolean mOpen = true;
     private int mOpenCount = 1;
 
-    private static final native int nativeCreate(byte[] data,
+    private static final native long nativeCreate(byte[] data,
                                                  int offset,
                                                  int size);
-    private static final native int nativeGetStringBlock(int obj);
+    private static final native long nativeGetStringBlock(long obj);
 
-    private static final native int nativeCreateParseState(int obj);
-    /*package*/ static final native int nativeNext(int state);
-    private static final native int nativeGetNamespace(int state);
-    /*package*/ static final native int nativeGetName(int state);
-    private static final native int nativeGetText(int state);
-    private static final native int nativeGetLineNumber(int state);
-    private static final native int nativeGetAttributeCount(int state);
-    private static final native int nativeGetAttributeNamespace(int state, int idx);
-    private static final native int nativeGetAttributeName(int state, int idx);
-    private static final native int nativeGetAttributeResource(int state, int idx);
-    private static final native int nativeGetAttributeDataType(int state, int idx);
-    private static final native int nativeGetAttributeData(int state, int idx);
-    private static final native int nativeGetAttributeStringValue(int state, int idx);
-    private static final native int nativeGetIdAttribute(int state);
-    private static final native int nativeGetClassAttribute(int state);
-    private static final native int nativeGetStyleAttribute(int state);
-    private static final native int nativeGetAttributeIndex(int state, String namespace, String name);
-    private static final native void nativeDestroyParseState(int state);
+    private static final native long nativeCreateParseState(long obj);
+    /*package*/ static final native int nativeNext(long state);
+    private static final native int nativeGetNamespace(long state);
+    /*package*/ static final native int nativeGetName(long state);
+    private static final native int nativeGetText(long state);
+    private static final native int nativeGetLineNumber(long state);
+    private static final native int nativeGetAttributeCount(long state);
+    private static final native int nativeGetAttributeNamespace(long state, int idx);
+    private static final native int nativeGetAttributeName(long state, int idx);
+    private static final native int nativeGetAttributeResource(long state, int idx);
+    private static final native int nativeGetAttributeDataType(long state, int idx);
+    private static final native int nativeGetAttributeData(long state, int idx);
+    private static final native int nativeGetAttributeStringValue(long state, int idx);
+    private static final native int nativeGetIdAttribute(long state);
+    private static final native int nativeGetClassAttribute(long state);
+    private static final native int nativeGetStyleAttribute(long state);
+    private static final native int nativeGetAttributeIndex(long state, String namespace, String name);
+    private static final native void nativeDestroyParseState(long state);
 
-    private static final native void nativeDestroy(int obj);
+    private static final native void nativeDestroy(long obj);
 }
diff --git a/core/java/android/debug/JNITest.java b/core/java/android/debug/JNITest.java
deleted file mode 100644
index 2ce374a..0000000
--- a/core/java/android/debug/JNITest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-package android.debug;
-
-/**
- * Simple JNI verification test.
- */
-public class JNITest {
-
-    public JNITest() {
-    }
-
-    public int test(int intArg, double doubleArg, String stringArg) {
-        int[] intArray = { 42, 53, 65, 127 };
-
-        return part1(intArg, doubleArg, stringArg, intArray);
-    }
-
-    private native int part1(int intArg, double doubleArg, String stringArg,
-        int[] arrayArg);
-
-    private int part2(double doubleArg, int fromArray, String stringArg) {
-        int result;
-
-        System.out.println(stringArg + " : " + (float) doubleArg + " : " +
-            fromArray);
-        result = part3(stringArg);
-
-        return result + 6;
-    }
-
-    private static native int part3(String stringArg);
-}
-
diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java
index 8fd8695..aba990d 100644
--- a/core/java/android/emoji/EmojiFactory.java
+++ b/core/java/android/emoji/EmojiFactory.java
@@ -54,7 +54,7 @@
     }
     
     // A pointer to native EmojiFactory object.
-    private int mNativeEmojiFactory;
+    private long mNativeEmojiFactory;
     private String mName;
     // Cache.
     private Map<Integer, WeakReference<Bitmap>> mCache;
@@ -68,7 +68,7 @@
      *
      * This can be called from JNI code.
      */
-    private EmojiFactory(int nativeEmojiFactory, String name) {
+    private EmojiFactory(long nativeEmojiFactory, String name) {
         mNativeEmojiFactory = nativeEmojiFactory;
         mName = name;
         mCache = new CustomLinkedHashMap<Integer, WeakReference<Bitmap>>();
@@ -272,18 +272,18 @@
     
     // native methods
     
-    private native void nativeDestructor(int factory);
-    private native Bitmap nativeGetBitmapFromAndroidPua(int nativeEmojiFactory, int AndroidPua);
-    private native int nativeGetAndroidPuaFromVendorSpecificSjis(int nativeEmojiFactory,
+    private native void nativeDestructor(long nativeEmojiFactory);
+    private native Bitmap nativeGetBitmapFromAndroidPua(long nativeEmojiFactory, int AndroidPua);
+    private native int nativeGetAndroidPuaFromVendorSpecificSjis(long nativeEmojiFactory,
             char sjis);
-    private native int nativeGetVendorSpecificSjisFromAndroidPua(int nativeEmojiFactory,
+    private native int nativeGetVendorSpecificSjisFromAndroidPua(long nativeEmojiFactory,
             int pua);
-    private native int nativeGetAndroidPuaFromVendorSpecificPua(int nativeEmojiFactory,
+    private native int nativeGetAndroidPuaFromVendorSpecificPua(long nativeEmojiFactory,
             int vsp);
-    private native int nativeGetVendorSpecificPuaFromAndroidPua(int nativeEmojiFactory,
+    private native int nativeGetVendorSpecificPuaFromAndroidPua(long nativeEmojiFactory,
             int pua);
-    private native int nativeGetMaximumVendorSpecificPua(int nativeEmojiFactory);
-    private native int nativeGetMinimumVendorSpecificPua(int nativeEmojiFactory);
-    private native int nativeGetMaximumAndroidPua(int nativeEmojiFactory);
-    private native int nativeGetMinimumAndroidPua(int nativeEmojiFactory);
+    private native int nativeGetMaximumVendorSpecificPua(long nativeEmojiFactory);
+    private native int nativeGetMinimumVendorSpecificPua(long nativeEmojiFactory);
+    private native int nativeGetMaximumAndroidPua(long nativeEmojiFactory);
+    private native int nativeGetMinimumAndroidPua(long nativeEmojiFactory);
 }
diff --git a/core/java/android/os/CountDownTimer.java b/core/java/android/os/CountDownTimer.java
index 15e6405..58acbcf 100644
--- a/core/java/android/os/CountDownTimer.java
+++ b/core/java/android/os/CountDownTimer.java
@@ -16,8 +16,6 @@
 
 package android.os;
 
-import android.util.Log;
-
 /**
  * Schedule a countdown until a time in the future, with
  * regular notifications on intervals along the way.
@@ -56,6 +54,11 @@
     private final long mCountdownInterval;
 
     private long mStopTimeInFuture;
+    
+    /**
+    * boolean representing if the timer was cancelled
+    */
+    private boolean mCancelled = false;
 
     /**
      * @param millisInFuture The number of millis in the future from the call
@@ -72,7 +75,8 @@
     /**
      * Cancel the countdown.
      */
-    public final void cancel() {
+    public synchronized final void cancel() {
+        mCancelled = true;
         mHandler.removeMessages(MSG);
     }
 
@@ -80,6 +84,7 @@
      * Start the countdown.
      */
     public synchronized final CountDownTimer start() {
+        mCancelled = false;
         if (mMillisInFuture <= 0) {
             onFinish();
             return this;
@@ -112,6 +117,10 @@
         public void handleMessage(Message msg) {
 
             synchronized (CountDownTimer.this) {
+                if (mCancelled) {
+                    return;
+                }
+
                 final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
 
                 if (millisLeft <= 0) {
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 6716098..7425f67 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1246,9 +1246,6 @@
         } else if (v instanceof Parcelable[]) {
             writeInt(VAL_PARCELABLEARRAY);
             writeParcelableArray((Parcelable[]) v, 0);
-        } else if (v instanceof Object[]) {
-            writeInt(VAL_OBJECTARRAY);
-            writeArray((Object[]) v);
         } else if (v instanceof int[]) {
             writeInt(VAL_INTARRAY);
             writeIntArray((int[]) v);
@@ -1258,12 +1255,20 @@
         } else if (v instanceof Byte) {
             writeInt(VAL_BYTE);
             writeInt((Byte) v);
-        } else if (v instanceof Serializable) {
-            // Must be last
-            writeInt(VAL_SERIALIZABLE);
-            writeSerializable((Serializable) v);
         } else {
-            throw new RuntimeException("Parcel: unable to marshal value " + v);
+            Class<?> clazz = v.getClass();
+            if (clazz.isArray() && clazz.getComponentType() == Object.class) {
+                // Only pure Object[] are written here, Other arrays of non-primitive types are
+                // handled by serialization as this does not record the component type.
+                writeInt(VAL_OBJECTARRAY);
+                writeArray((Object[]) v);
+            } else if (v instanceof Serializable) {
+                // Must be last
+                writeInt(VAL_SERIALIZABLE);
+                writeSerializable((Serializable) v);
+            } else {
+                throw new RuntimeException("Parcel: unable to marshal value " + v);
+            }
         }
     }
 
@@ -1454,10 +1459,11 @@
     }
 
     /**
-     * Use this function for customized exception handling.
-     * customized method call this method for all unknown case
-     * @param code exception code
-     * @param msg exception message
+     * Throw an exception with the given message. Not intended for use
+     * outside the Parcel class.
+     *
+     * @param code Used to determine which exception class to throw.
+     * @param msg The exception message.
      */
     public final void readException(int code, String msg) {
         switch (code) {
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 729c64b..672df6d 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import android.app.IAlarmManager;
+import android.content.Context;
+import android.util.Slog;
 
 /**
  * Core timekeeping facilities.
@@ -89,6 +92,8 @@
  * </ul>
  */
 public final class SystemClock {
+    private static final String TAG = "SystemClock";
+
     /**
      * This class is uninstantiable.
      */
@@ -134,7 +139,23 @@
      *
      * @return if the clock was successfully set to the specified time.
      */
-    native public static boolean setCurrentTimeMillis(long millis);
+    public static boolean setCurrentTimeMillis(long millis) {
+        IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
+        IAlarmManager mgr = IAlarmManager.Stub.asInterface(b);
+        if (mgr == null) {
+            return false;
+        }
+
+        try {
+            return mgr.setTime(millis);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to set RTC", e);
+        } catch (SecurityException e) {
+            Slog.e(TAG, "Unable to set RTC", e);
+        }
+
+        return false;
+    }
 
     /**
      * Returns milliseconds since boot, not counting time spent in deep sleep.
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java
index f2a86c9..7d1c6c4 100644
--- a/core/java/android/util/JsonReader.java
+++ b/core/java/android/util/JsonReader.java
@@ -546,6 +546,9 @@
     public void skipValue() throws IOException {
         skipping = true;
         try {
+            if (!hasNext() || peek() == JsonToken.END_DOCUMENT) {
+                throw new IllegalStateException("No element left to skip");
+            }
             int count = 0;
             do {
                 JsonToken token = advance();
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 6a15fa6..d533060 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -392,11 +392,11 @@
     // Atlas
     ///////////////////////////////////////////////////////////////////////////
 
-    static void initAtlas(GraphicBuffer buffer, int[] map) {
+    static void initAtlas(GraphicBuffer buffer, long[] map) {
         nInitAtlas(buffer, map, map.length);
     }
 
-    private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count);
+    private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count);
 
     ///////////////////////////////////////////////////////////////////////////
     // Display list
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 3781bdb..f09a111 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1981,7 +1981,7 @@
                 if (atlas.isCompatible(android.os.Process.myPpid())) {
                     GraphicBuffer buffer = atlas.getBuffer();
                     if (buffer != null) {
-                        int[] map = atlas.getMap();
+                        long[] map = atlas.getMap();
                         if (map != null) {
                             GLES20Canvas.initAtlas(buffer, map);
                         }
diff --git a/core/java/android/view/IAssetAtlas.aidl b/core/java/android/view/IAssetAtlas.aidl
index 5f1e238..edce059 100644
--- a/core/java/android/view/IAssetAtlas.aidl
+++ b/core/java/android/view/IAssetAtlas.aidl
@@ -45,10 +45,10 @@
      * if the atlas is not available yet.
      *
      * Each bitmap is represented by several entries in the array:
-     * int0: SkBitmap*, the native bitmap object
-     * int1: x position
-     * int2: y position
-     * int3: rotated, 1 if the bitmap must be rotated, 0 otherwise
+     * long0: SkBitmap*, the native bitmap object
+     * long1: x position
+     * long2: y position
+     * long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
      */
-    int[] getMap();
+    long[] getMap();
 }
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 0dfd94a..3cf5af4 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -24,11 +24,11 @@
  */
 public final class SurfaceSession {
     // Note: This field is accessed by native code.
-    private int mNativeClient; // SurfaceComposerClient*
+    private long mNativeClient; // SurfaceComposerClient*
 
-    private static native int nativeCreate();
-    private static native void nativeDestroy(int ptr);
-    private static native void nativeKill(int ptr);
+    private static native long nativeCreate();
+    private static native void nativeDestroy(long ptr);
+    private static native void nativeKill(long ptr);
 
     /** Create a new connection with the surface flinger. */
     public SurfaceSession() {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b0bae46..83610c3c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11838,7 +11838,7 @@
     }
 
     /**
-     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
+     * <p>Compute the vertical extent of the vertical scrollbar's thumb
      * within the vertical range. This value is used to compute the length
      * of the thumb within the scrollbar's track.</p>
      *
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index a5fad60..a06344f 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -663,7 +663,7 @@
 
     /**
      * When the current adapter is empty, the AdapterView can display a special view
-     * call the empty view. The empty view is used to provide feedback to the user
+     * called the empty view. The empty view is used to provide feedback to the user
      * that no data is available in this AdapterView.
      *
      * @return The view to show if the adapter is empty.
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 0cad33c..a87992a 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -1046,7 +1046,7 @@
 
     public boolean evaluateSystemProperties(boolean update) {
         boolean changed = false;
-        String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib",
+        String runtime = SystemProperties.get("persist.sys.dalvik.vm.lib.1",
                 VMRuntime.getRuntime().vmLibrary());
         if (!Objects.equals(runtime, mRuntime)) {
             changed = true;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4f3b5b3..f9a1f89 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -224,9 +224,37 @@
                 ZygoteInit.setCloseOnExec(serverPipeFd, true);
             }
 
+            /**
+             * In order to avoid leaking descriptors to the Zygote child,
+             * the native code must close the two Zygote socket descriptors
+             * in the child process before it switches from Zygote-root to
+             * the UID and privileges of the application being launched.
+             *
+             * In order to avoid "bad file descriptor" errors when the
+             * two LocalSocket objects are closed, the Posix file
+             * descriptors are released via a dup2() call which closes
+             * the socket and substitutes an open descriptor to /dev/null.
+             */
+
+            int [] fdsToClose = { -1, -1 };
+
+            FileDescriptor fd = mSocket.getFileDescriptor();
+
+            if (fd != null) {
+                fdsToClose[0] = fd.getInt$();
+            }
+
+            fd = ZygoteInit.getServerSocketFileDescriptor();
+
+            if (fd != null) {
+                fdsToClose[1] = fd.getInt$();
+            }
+
+            fd = null;
+
             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                     parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
-                    parsedArgs.niceName);
+                    parsedArgs.niceName, fdsToClose);
         } catch (IOException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
         } catch (ErrnoException ex) {
@@ -814,6 +842,12 @@
             FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
             throws ZygoteInit.MethodAndArgsCaller {
 
+        /**
+         * By the time we get here, the native code has closed the two actual Zygote
+         * socket connections, and substituted /dev/null in their place.  The LocalSocket
+         * objects still need to be closed properly.
+         */
+
         closeSocket();
         ZygoteInit.closeServerSocket();
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 55d5513..4bf13fc 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -207,6 +207,16 @@
         sServerSocket = null;
     }
 
+    /**
+     * Return the server socket's underlying file descriptor, so that
+     * ZygoteConnection can pass it to the native code for proper
+     * closure after a child process is forked off.
+     */
+
+    static FileDescriptor getServerSocketFileDescriptor() {
+        return sServerSocket.getFileDescriptor();
+    }
+
     private static final int UNPRIVILEGED_UID = 9999;
     private static final int UNPRIVILEGED_GID = 9999;
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 2e0acb1..ac70738 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -134,7 +134,6 @@
 	android_hardware_UsbDevice.cpp \
 	android_hardware_UsbDeviceConnection.cpp \
 	android_hardware_UsbRequest.cpp \
-	android_debug_JNITest.cpp \
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 97ea5e6..2215dd7 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,7 +131,6 @@
 extern int register_android_database_SQLiteConnection(JNIEnv* env);
 extern int register_android_database_SQLiteGlobal(JNIEnv* env);
 extern int register_android_database_SQLiteDebug(JNIEnv* env);
-extern int register_android_debug_JNITest(JNIEnv* env);
 extern int register_android_nio_utils(JNIEnv* env);
 extern int register_android_text_format_Time(JNIEnv* env);
 extern int register_android_os_Debug(JNIEnv* env);
@@ -760,13 +759,6 @@
         mOptions.add(opt);
     }
 
-    /*
-     * We don't have /tmp on the device, but we often have an SD card.  Apps
-     * shouldn't use this, but some test suites might want to exercise it.
-     */
-    opt.optionString = "-Djava.io.tmpdir=/sdcard";
-    mOptions.add(opt);
-
     initArgs.version = JNI_VERSION_1_4;
     initArgs.options = mOptions.editArray();
     initArgs.nOptions = mOptions.size();
@@ -1100,7 +1092,6 @@
 }
 
 static const RegJNIRec gRegJNI[] = {
-    REG_JNI(register_android_debug_JNITest),
     REG_JNI(register_com_android_internal_os_RuntimeInit),
     REG_JNI(register_android_os_SystemClock),
     REG_JNI(register_android_util_EventLog),
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 89490bc..11089da 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -321,9 +321,10 @@
     }
 
     static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
-                             SkPath* path, jint op) {
+                             jlong pathHandle, jint op) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        bool result = canvas->clipPath(*path, static_cast<SkRegion::Op>(op));
+        bool result = canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
+                                       static_cast<SkRegion::Op>(op));
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
@@ -336,9 +337,9 @@
     }
 
     static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
-                              SkDrawFilter* filter) {
+                              jlong filterHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        canvas->setDrawFilter(filter);
+        canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
     }
 
     static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
@@ -350,9 +351,9 @@
     }
 
     static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
-                                       SkPath* path) {
+                                       jlong pathHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        bool result = canvas->quickReject(*path);
+        bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 6175a8f..d54aaa8 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -113,24 +113,24 @@
     PageRecord* mCurrentPage;
 };
 
-static jint nativeCreateDocument(JNIEnv* env, jobject thiz) {
-    return reinterpret_cast<jint>(new PdfDocument());
+static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) {
+    return reinterpret_cast<jlong>(new PdfDocument());
 }
 
-static jint nativeStartPage(JNIEnv* env, jobject thiz, jint documentPtr,
+static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
         jint pageWidth, jint pageHeight,
         jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
     PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
-    return reinterpret_cast<jint>(document->startPage(pageWidth, pageHeight,
+    return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight,
             contentLeft, contentTop, contentRight, contentBottom));
 }
 
-static void nativeFinishPage(JNIEnv* env, jobject thiz, jint documentPtr) {
+static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
     PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
     document->finishPage();
 }
 
-static void nativeWriteTo(JNIEnv* env, jobject thiz, jint documentPtr, jobject out,
+static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out,
         jbyteArray chunk) {
     PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
     SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
@@ -138,17 +138,17 @@
     delete skWStream;
 }
 
-static void nativeClose(JNIEnv* env, jobject thiz, jint documentPtr) {
+static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) {
     PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
     document->close();
 }
 
 static JNINativeMethod gPdfDocument_Methods[] = {
-    {"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
-    {"nativeStartPage", "(IIIIIII)I", (void*) nativeStartPage},
-    {"nativeFinishPage", "(I)V", (void*) nativeFinishPage},
-    {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
-    {"nativeClose", "(I)V", (void*) nativeClose}
+    {"nativeCreateDocument", "()J", (void*) nativeCreateDocument},
+    {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage},
+    {"nativeFinishPage", "(J)V", (void*) nativeFinishPage},
+    {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
+    {"nativeClose", "(J)V", (void*) nativeClose}
 };
 
 int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
diff --git a/core/jni/android_animation_PropertyValuesHolder.cpp b/core/jni/android_animation_PropertyValuesHolder.cpp
index 5991805..1e3ec18 100644
--- a/core/jni/android_animation_PropertyValuesHolder.cpp
+++ b/core/jni/android_animation_PropertyValuesHolder.cpp
@@ -29,44 +29,44 @@
 
 const char* const kClassPathName = "android/animation/PropertyValuesHolder";
 
-static jmethodID android_animation_PropertyValuesHolder_getIntMethod(
+static jlong android_animation_PropertyValuesHolder_getIntMethod(
         JNIEnv* env, jclass pvhClass, jclass targetClass, jstring methodName)
 {
     const char *nativeString = env->GetStringUTFChars(methodName, 0);
     jmethodID mid = env->GetMethodID(targetClass, nativeString, "(I)V");
     env->ReleaseStringUTFChars(methodName, nativeString);
-    return mid;
+    return reinterpret_cast<jlong>(mid);
 }
 
-static jmethodID android_animation_PropertyValuesHolder_getFloatMethod(
+static jlong android_animation_PropertyValuesHolder_getFloatMethod(
         JNIEnv* env, jclass pvhClass, jclass targetClass, jstring methodName)
 {
     const char *nativeString = env->GetStringUTFChars(methodName, 0);
     jmethodID mid = env->GetMethodID(targetClass, nativeString, "(F)V");
     env->ReleaseStringUTFChars(methodName, nativeString);
-    return mid;
+    return reinterpret_cast<jlong>(mid);
 }
 
 static void android_animation_PropertyValuesHolder_callIntMethod(
-        JNIEnv* env, jclass pvhObject, jobject target, jmethodID methodID, int arg)
+        JNIEnv* env, jclass pvhObject, jobject target, jlong methodID, jint arg)
 {
-    env->CallVoidMethod(target, methodID, arg);
+    env->CallVoidMethod(target, reinterpret_cast<jmethodID>(methodID), arg);
 }
 
 static void android_animation_PropertyValuesHolder_callFloatMethod(
-        JNIEnv* env, jclass pvhObject, jobject target, jmethodID methodID, float arg)
+        JNIEnv* env, jclass pvhObject, jobject target, jlong methodID, jfloat arg)
 {
-    env->CallVoidMethod(target, methodID, arg);
+    env->CallVoidMethod(target, reinterpret_cast<jmethodID>(methodID), arg);
 }
 
 static JNINativeMethod gMethods[] = {
-    {   "nGetIntMethod", "(Ljava/lang/Class;Ljava/lang/String;)I",
+    {   "nGetIntMethod", "(Ljava/lang/Class;Ljava/lang/String;)J",
             (void*)android_animation_PropertyValuesHolder_getIntMethod },
-    {   "nGetFloatMethod", "(Ljava/lang/Class;Ljava/lang/String;)I",
+    {   "nGetFloatMethod", "(Ljava/lang/Class;Ljava/lang/String;)J",
             (void*)android_animation_PropertyValuesHolder_getFloatMethod },
-    {   "nCallIntMethod", "(Ljava/lang/Object;II)V",
+    {   "nCallIntMethod", "(Ljava/lang/Object;JI)V",
             (void*)android_animation_PropertyValuesHolder_callIntMethod },
-    {   "nCallFloatMethod", "(Ljava/lang/Object;IF)V",
+    {   "nCallFloatMethod", "(Ljava/lang/Object;JF)V",
             (void*)android_animation_PropertyValuesHolder_callFloatMethod }
 };
 
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index acc2276..89d64fa 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -39,7 +39,7 @@
     bool verboseLog = !!data;
     if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT || iErrCode == SQLITE_SCHEMA) {
         if (verboseLog) {
-            ALOGV(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
+            ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
         }
     } else {
         ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
diff --git a/core/jni/android_debug_JNITest.cpp b/core/jni/android_debug_JNITest.cpp
deleted file mode 100644
index 9147284..0000000
--- a/core/jni/android_debug_JNITest.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* //device/libs/android_runtime/android_debug_JNITest.cpp
-**
-** Copyright 2006, 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.
-*/
-
-#define LOG_TAG "DebugJNI"
-
-#include "jni.h"
-#include "nativehelper/JNIHelp.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-//#include "android_runtime/AndroidRuntime.h"
-
-namespace android {
-
-/*
- * Implements:
- *  native int part1(int intArg, double doubleArg, String stringArg,
- *      int[] arrayArg)
- */
-static jint android_debug_JNITest_part1(JNIEnv* env, jobject object,
-    jint intArg, jdouble doubleArg, jstring stringArg, jobjectArray arrayArg)
-{
-    jclass clazz;
-    jmethodID part2id;
-    jsize arrayLen;
-    jint arrayVal;
-    int result = -2;
-
-    ALOGI("JNI test: in part1, intArg=%d, doubleArg=%.3f\n", intArg, doubleArg);
-
-    /* find "int part2(double doubleArg, int fromArray, String stringArg)" */
-    clazz = env->GetObjectClass(object);
-    part2id = env->GetMethodID(clazz,
-                "part2", "(DILjava/lang/String;)I");
-    if (part2id == NULL) {
-        ALOGE("JNI test: unable to find part2\n");
-        return -1;
-    }
-
-    /* get the length of the array */
-    arrayLen = env->GetArrayLength(arrayArg);
-    ALOGI("  array size is %d\n", arrayLen);
-
-    /*
-     * Get the last element in the array.
-     * Use the Get<type>ArrayElements functions instead if you need access
-     * to multiple elements.
-     */
-    arrayVal = (int) env->GetObjectArrayElement(arrayArg, arrayLen-1);
-    ALOGI("  array val is %d\n", arrayVal);
-
-    /* call this->part2 */
-    result = env->CallIntMethod(object, part2id,
-        doubleArg, arrayVal, stringArg);
-
-    return result;
-}
-
-/*
- * Implements:
- *  private static native int part3(String stringArg);
- */
-static jint android_debug_JNITest_part3(JNIEnv* env, jclass clazz,
-    jstring stringArg)
-{
-    const char* utfChars;
-    jboolean isCopy;
-
-    ALOGI("JNI test: in part3\n");
-
-    utfChars = env->GetStringUTFChars(stringArg, &isCopy);
-
-    ALOGI("  String is '%s', isCopy=%d\n", (const char*) utfChars, isCopy);
-
-    env->ReleaseStringUTFChars(stringArg, utfChars);
-
-    return 2000;
-}
-
-/*
- * JNI registration.
- */
-static JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "part1",      "(IDLjava/lang/String;[I)I",
-            (void*) android_debug_JNITest_part1 },
-    { "part3",      "(Ljava/lang/String;)I",
-            (void*) android_debug_JNITest_part3 },
-};
-int register_android_debug_JNITest(JNIEnv* env)
-{
-    return jniRegisterNativeMethods(env, "android/debug/JNITest",
-        gMethods, NELEM(gMethods));
-}
-
-#if 0
-/* trampoline into C++ */
-extern "C"
-int register_android_debug_JNITest_C(JNIEnv* env)
-{
-    return android::register_android_debug_JNITest(env);
-}
-#endif
-
-}; // namespace android
-
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index 5276934..f127d29 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -104,7 +104,7 @@
 static jobject create_java_EmojiFactory(
     JNIEnv* env, EmojiFactory* factory, jstring name) {
   jobject obj = env->NewObject(gEmojiFactory_class, gEmojiFactory_constructorMethodID,
-      static_cast<jint>(reinterpret_cast<uintptr_t>(factory)), name);
+      reinterpret_cast<jlong>(factory), name);
   if (env->ExceptionCheck() != 0) {
     ALOGE("*** Uncaught exception returned from Java call!\n");
     env->ExceptionDescribe();
@@ -155,7 +155,7 @@
 }
 
 static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
-    JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) {
+    JNIEnv* env, jobject clazz, jlong nativeEmojiFactory, jint pua) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
 
   int size;
@@ -175,7 +175,7 @@
 }
 
 static void android_emoji_EmojiFactory_destructor(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
   /*
   // Must not delete this object!!
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
@@ -184,49 +184,49 @@
 }
 
 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jchar sjis) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
 }
 
 static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetVendorSpecificSjisFromAndroidPua(pua);
 }
 
 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint vsu) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
 }
 
 static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetVendorSpecificPuaFromAndroidPua(pua);
 }
 
 static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetMaximumVendorSpecificPua();
 }
 
 static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetMinimumVendorSpecificPua();
 }
 
 static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetMaximumAndroidPua();
 }
 
 static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
-    JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+    JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   return factory->GetMinimumAndroidPua();
 }
@@ -236,25 +236,25 @@
     (void*)android_emoji_EmojiFactory_newInstance},
   { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
     (void*)android_emoji_EmojiFactory_newAvailableInstance},
-  { "nativeDestructor", "(I)V",
+  { "nativeDestructor", "(J)V",
     (void*)android_emoji_EmojiFactory_destructor},
-  { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;",
+  { "nativeGetBitmapFromAndroidPua", "(JI)Landroid/graphics/Bitmap;",
     (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
-  { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I",
+  { "nativeGetAndroidPuaFromVendorSpecificSjis", "(JC)I",
     (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
-  { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I",
+  { "nativeGetVendorSpecificSjisFromAndroidPua", "(JI)I",
     (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
-  { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I",
+  { "nativeGetAndroidPuaFromVendorSpecificPua", "(JI)I",
     (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
-  { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I",
+  { "nativeGetVendorSpecificPuaFromAndroidPua", "(JI)I",
     (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
-  { "nativeGetMaximumVendorSpecificPua", "(I)I",
+  { "nativeGetMaximumVendorSpecificPua", "(J)I",
     (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
-  { "nativeGetMinimumVendorSpecificPua", "(I)I",
+  { "nativeGetMinimumVendorSpecificPua", "(J)I",
     (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
-  { "nativeGetMaximumAndroidPua", "(I)I",
+  { "nativeGetMaximumAndroidPua", "(J)I",
     (void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
-  { "nativeGetMinimumAndroidPua", "(I)I",
+  { "nativeGetMinimumAndroidPua", "(J)I",
     (void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
 };
 
@@ -276,7 +276,7 @@
 int register_android_emoji_EmojiFactory(JNIEnv* env) {
   gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
   gEmojiFactory_constructorMethodID = env->GetMethodID(
-      gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
+      gEmojiFactory_class, "<init>", "(JLjava/lang/String;)V");
   return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
                                   gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 5b0a4b2..19e4d99 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -69,22 +69,22 @@
     jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
     eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
 
-    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
-    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
 
 
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
 
-    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
     eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
     eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
     eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
 
 
@@ -106,7 +106,8 @@
                           "Object is set to null.");
     }
 
-    return (void*) (_env->CallIntMethod(obj, mid));
+    jlong handle = _env->CallLongMethod(obj, mid);
+    return reinterpret_cast<void*>(handle);
 }
 
 static jobject
@@ -126,7 +127,7 @@
            return eglNoSurfaceObject;
     }
 
-    return _env->NewObject(cls, con, (jint)handle);
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
 // --------------------------------------------------------------------------
@@ -142,14 +143,26 @@
 /* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
 static jobject
 android_eglGetDisplay
-  (JNIEnv *_env, jobject _this, jint display_id) {
+  (JNIEnv *_env, jobject _this, jlong display_id) {
     EGLDisplay _returnValue = (EGLDisplay) 0;
     _returnValue = eglGetDisplay(
-        (EGLNativeDisplayType)display_id
+        reinterpret_cast<EGLNativeDisplayType>(display_id)
     );
     return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
 }
 
+/* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
+static jobject
+android_eglGetDisplayInt
+  (JNIEnv *_env, jobject _this, jint display_id) {
+
+    if ((EGLNativeDisplayType)display_id != EGL_DEFAULT_DISPLAY) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglGetDisplay");
+        return 0;
+    }
+    return android_eglGetDisplay(_env, _this, display_id);
+}
+
 /* EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor ) */
 static jboolean
 android_eglInitialize
@@ -852,7 +865,7 @@
 /* EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list ) */
 static jobject
 android_eglCreatePbufferFromClientBuffer
-  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jlong buffer, jobject config, jintArray attrib_list_ref, jint offset) {
     jint _exception = 0;
     const char * _exceptionType = NULL;
     const char * _exceptionMessage = NULL;
@@ -897,7 +910,7 @@
     _returnValue = eglCreatePbufferFromClientBuffer(
         (EGLDisplay)dpy_native,
         (EGLenum)buftype,
-        (EGLClientBuffer)buffer,
+        reinterpret_cast<EGLClientBuffer>(buffer),
         (EGLConfig)config_native,
         (EGLint *)attrib_list
     );
@@ -913,6 +926,16 @@
     return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
 }
 
+static jobject
+android_eglCreatePbufferFromClientBufferInt
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+    if(sizeof(void*) != sizeof(uint32_t)) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglCreatePbufferFromClientBuffer");
+        return 0;
+    }
+    return android_eglCreatePbufferFromClientBuffer(_env, _this, dpy, buftype, buffer, config, attrib_list_ref, offset);
+}
+
 /* EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value ) */
 static jboolean
 android_eglSurfaceAttrib
@@ -1207,7 +1230,8 @@
 static JNINativeMethod methods[] = {
 {"_nativeClassInit", "()V", (void*)nativeClassInit },
 {"eglGetError", "()I", (void *) android_eglGetError },
-{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
+{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplayInt },
+{"eglGetDisplay", "(J)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
 {"eglInitialize", "(Landroid/opengl/EGLDisplay;[II[II)Z", (void *) android_eglInitialize },
 {"eglTerminate", "(Landroid/opengl/EGLDisplay;)Z", (void *) android_eglTerminate },
 {"eglQueryString", "(Landroid/opengl/EGLDisplay;I)Ljava/lang/String;", (void *) android_eglQueryString__Landroind_opengl_EGLDisplay_2I },
@@ -1224,7 +1248,8 @@
 {"eglQueryAPI", "()I", (void *) android_eglQueryAPI },
 {"eglWaitClient", "()Z", (void *) android_eglWaitClient },
 {"eglReleaseThread", "()Z", (void *) android_eglReleaseThread },
-{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBufferInt },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IJLandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
 {"eglSurfaceAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;II)Z", (void *) android_eglSurfaceAttrib },
 {"eglBindTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglBindTexImage },
 {"eglReleaseTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglReleaseTexImage },
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index 5179ddc..15899f5 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -70,22 +70,22 @@
     jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
     eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
 
-    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
-    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
 
 
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
 
-    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
     eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
     eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
     eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
 
 
@@ -107,7 +107,7 @@
                           "Object is set to null.");
     }
 
-    return (void*) (_env->CallIntMethod(obj, mid));
+    return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
 }
 
 static jobject
@@ -127,7 +127,7 @@
            return eglNoSurfaceObject;
     }
 
-    return _env->NewObject(cls, con, (jint)handle);
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
 // --------------------------------------------------------------------------
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index cc34e99..21e19e1 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 9284384..bc83234 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 871e84d..a45f269 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -578,7 +578,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -679,7 +679,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -2302,7 +2302,7 @@
     glNormalPointer(
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2529,7 +2529,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2937,7 +2937,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 3e038ad..05728ef 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index db03b70..d3e5014 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -1180,7 +1180,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -1804,7 +1804,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        (char *)name
+        reinterpret_cast<char *>(name)
     );
     if (_typeArray) {
         releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -2132,7 +2132,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        (char *)name
+        reinterpret_cast<char *>(name)
     );
     if (_typeArray) {
         releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -3212,7 +3212,7 @@
         (GLuint)shader,
         (GLsizei)bufsize,
         (GLsizei *)length,
-        (char *)source
+        reinterpret_cast<char *>(source)
     );
     if (_array) {
         releasePointer(_env, _array, length, JNI_TRUE);
@@ -5985,7 +5985,7 @@
         (GLenum)type,
         (GLboolean)normalized,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 4c62a75..8821352 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -370,7 +370,7 @@
         (GLuint)end,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -419,7 +419,7 @@
         (GLint)border,
         (GLenum)format,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -470,7 +470,7 @@
         (GLsizei)depth,
         (GLenum)format,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -534,7 +534,7 @@
         (GLsizei)depth,
         (GLint)border,
         (GLsizei)imageSize,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -585,7 +585,7 @@
         (GLsizei)depth,
         (GLenum)format,
         (GLsizei)imageSize,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2134,7 +2134,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index ca278cf..26405b5 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -411,11 +411,11 @@
 
     ScopedUtfChars pathname(env, pathnameStr);
     if (pathname.c_str() == NULL) {
-        ALOGV("restorecon(%p) => threw exception", pathname);
+        ALOGV("restorecon(%p) => threw exception", pathnameStr);
         return false;
     }
 
-    int ret = selinux_android_restorecon(pathname.c_str());
+    int ret = selinux_android_restorecon(pathname.c_str(), 0);
     ALOGV("restorecon(%s) => %d", pathname.c_str(), ret);
     return (ret == 0);
 }
@@ -443,8 +443,21 @@
 
 static int log_callback(int type, const char *fmt, ...) {
     va_list ap;
+    int priority;
+
+    switch (type) {
+    case SELINUX_WARNING:
+        priority = ANDROID_LOG_WARN;
+        break;
+    case SELINUX_INFO:
+        priority = ANDROID_LOG_INFO;
+        break;
+    default:
+        priority = ANDROID_LOG_ERROR;
+        break;
+    }
     va_start(ap, fmt);
-    LOG_PRI_VA(ANDROID_LOG_ERROR, "SELinux", fmt, ap);
+    LOG_PRI_VA(priority, "SELinux", fmt, ap);
     va_end(ap);
     return 0;
 }
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index 5f4d570..62478442 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -19,13 +19,6 @@
  * System clock functions.
  */
 
-#ifdef HAVE_ANDROID_OS
-#include <linux/ioctl.h>
-#include <linux/rtc.h>
-#include <utils/Atomic.h>
-#include <linux/android_alarm.h>
-#endif
-
 #include <sys/time.h>
 #include <limits.h>
 #include <fcntl.h>
@@ -43,109 +36,6 @@
 
 namespace android {
 
-static int setCurrentTimeMillisAlarmDriver(struct timeval *tv)
-{
-    struct timespec ts;
-    int fd;
-    int res;
-
-    fd = open("/dev/alarm", O_RDWR);
-    if(fd < 0) {
-        ALOGV("Unable to open alarm driver: %s\n", strerror(errno));
-        return -1;
-    }
-    ts.tv_sec = tv->tv_sec;
-    ts.tv_nsec = tv->tv_usec * 1000;
-    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
-    if (res < 0)
-        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
-    close(fd);
-    return res;
-}
-
-static int setCurrentTimeMillisRtc(struct timeval *tv)
-{
-    struct rtc_time rtc;
-    struct tm tm, *gmtime_res;
-    int fd;
-    int res;
-
-    fd = open("/dev/rtc0", O_RDWR);
-    if (fd < 0) {
-        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
-        return -1;
-    }
-
-    res = settimeofday(tv, NULL);
-    if (res < 0) {
-        ALOGV("settimeofday() failed: %s\n", strerror(errno));
-        goto done;
-    }
-
-    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
-    if (!gmtime_res) {
-        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
-        res = -1;
-        goto done;
-    }
-
-    memset(&rtc, 0, sizeof(rtc));
-    rtc.tm_sec = tm.tm_sec;
-    rtc.tm_min = tm.tm_min;
-    rtc.tm_hour = tm.tm_hour;
-    rtc.tm_mday = tm.tm_mday;
-    rtc.tm_mon = tm.tm_mon;
-    rtc.tm_year = tm.tm_year;
-    rtc.tm_wday = tm.tm_wday;
-    rtc.tm_yday = tm.tm_yday;
-    rtc.tm_isdst = tm.tm_isdst;
-    res = ioctl(fd, RTC_SET_TIME, &rtc);
-    if (res < 0)
-        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
-done:
-    close(fd);
-    return res;
-}
-
-/*
- * Set the current time.  This only works when running as root.
- */
-static int setCurrentTimeMillis(int64_t millis)
-{
-    struct timeval tv;
-    int ret;
-
-    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
-        return -1;
-    }
-
-    tv.tv_sec = (time_t) (millis / 1000LL);
-    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
-
-    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
-
-    ret = setCurrentTimeMillisAlarmDriver(&tv);
-    if (ret < 0)
-        ret = setCurrentTimeMillisRtc(&tv);
-
-    if(ret < 0) {
-        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
-        ret = -1;
-    }
-    return ret;
-}
-
-/*
- * native public static void setCurrentTimeMillis(long millis)
- *
- * Set the current time.  This only works when running as root.
- */
-static jboolean android_os_SystemClock_setCurrentTimeMillis(JNIEnv* env,
-    jobject clazz, jlong millis)
-{
-    return (setCurrentTimeMillis(millis) == 0);
-}
-
 /*
  * native public static long uptimeMillis();
  */
@@ -230,8 +120,6 @@
  */
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "setCurrentTimeMillis",      "(J)Z",
-            (void*) android_os_SystemClock_setCurrentTimeMillis },
     { "uptimeMillis",      "()J",
             (void*) android_os_SystemClock_uptimeMillis },
     { "elapsedRealtime",      "()J",
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 8836918..7162a1c 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -35,7 +35,16 @@
 #include <androidfw/AssetManager.h>
 #include <androidfw/ResourceTypes.h>
 
+#include <private/android_filesystem_config.h> // for AID_SYSTEM
+
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <linux/capability.h>
+extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
+extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
+
 
 namespace android {
 
@@ -88,7 +97,7 @@
 {
     env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
     env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
-                        (jint)table->getTableCookie(block));
+                     static_cast<jint>(table->getTableCookie(block)));
     env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
     env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
     env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
@@ -100,12 +109,70 @@
     return block;
 }
 
+// This is called by zygote (running as user root) as part of preloadResources.
+static void verifySystemIdmaps()
+{
+    pid_t pid;
+    char system_id[10];
+
+    snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
+
+    switch (pid = fork()) {
+        case -1:
+            ALOGE("failed to fork for idmap: %s", strerror(errno));
+            break;
+        case 0: // child
+            {
+                struct __user_cap_header_struct capheader;
+                struct __user_cap_data_struct capdata;
+
+                memset(&capheader, 0, sizeof(capheader));
+                memset(&capdata, 0, sizeof(capdata));
+
+                capheader.version = _LINUX_CAPABILITY_VERSION;
+                capheader.pid = 0;
+
+                if (capget(&capheader, &capdata) != 0) {
+                    ALOGE("capget: %s\n", strerror(errno));
+                    exit(1);
+                }
+
+                capdata.effective = capdata.permitted;
+                if (capset(&capheader, &capdata) != 0) {
+                    ALOGE("capset: %s\n", strerror(errno));
+                    exit(1);
+                }
+
+                if (setgid(AID_SYSTEM) != 0) {
+                    ALOGE("setgid: %s\n", strerror(errno));
+                    exit(1);
+                }
+
+                if (setuid(AID_SYSTEM) != 0) {
+                    ALOGE("setuid: %s\n", strerror(errno));
+                    exit(1);
+                }
+
+                execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
+                        AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
+                        AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
+                ALOGE("failed to execl for idmap: %s", strerror(errno));
+                exit(1); // should never get here
+            }
+            break;
+        default: // parent
+            waitpid(pid, NULL, 0);
+            break;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 // this guy is exported to other jni routines
 AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
 {
-    AssetManager* am = (AssetManager*)env->GetIntField(obj, gAssetManagerOffsets.mObject);
+    jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
+    AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
     if (am != NULL) {
         return am;
     }
@@ -113,7 +180,7 @@
     return NULL;
 }
 
-static jint android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
+static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
                                                 jstring fileName, jint mode)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
@@ -125,6 +192,7 @@
 
     ScopedUtfChars fileName8(env, fileName);
     if (fileName8.c_str() == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
         return -1;
     }
 
@@ -143,7 +211,7 @@
 
     //printf("Created Asset Stream: %p\n", a);
 
-    return (jint)a;
+    return reinterpret_cast<jlong>(a);
 }
 
 static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
@@ -205,7 +273,7 @@
     return returnParcelFileDescriptor(env, a, outOffsets);
 }
 
-static jint android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
+static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
                                                          jint cookie,
                                                          jstring fileName,
                                                          jint mode)
@@ -240,7 +308,7 @@
 
     //printf("Created Asset Stream: %p\n", a);
 
-    return (jint)a;
+    return reinterpret_cast<jlong>(a);
 }
 
 static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
@@ -320,9 +388,9 @@
 }
 
 static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
-                                                   jint asset)
+                                                      jlong assetHandle)
 {
-    Asset* a = (Asset*)asset;
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
 
     //printf("Destroying Asset Stream: %p\n", a);
 
@@ -335,9 +403,9 @@
 }
 
 static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
-                                                    jint asset)
+                                                       jlong assetHandle)
 {
-    Asset* a = (Asset*)asset;
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
 
     if (a == NULL) {
         jniThrowNullPointerException(env, "asset");
@@ -350,10 +418,10 @@
 }
 
 static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
-                                                jint asset, jbyteArray bArray,
+                                                jlong assetHandle, jbyteArray bArray,
                                                 jint off, jint len)
 {
-    Asset* a = (Asset*)asset;
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
 
     if (a == NULL || bArray == NULL) {
         jniThrowNullPointerException(env, "asset");
@@ -374,7 +442,7 @@
     ssize_t res = a->read(b+off, len);
     env->ReleaseByteArrayElements(bArray, b, 0);
 
-    if (res > 0) return res;
+    if (res > 0) return static_cast<jint>(res);
 
     if (res < 0) {
         jniThrowException(env, "java/io/IOException", "");
@@ -383,10 +451,10 @@
 }
 
 static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
-                                                 jint asset,
+                                                 jlong assetHandle,
                                                  jlong offset, jint whence)
 {
-    Asset* a = (Asset*)asset;
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
 
     if (a == NULL) {
         jniThrowNullPointerException(env, "asset");
@@ -398,9 +466,9 @@
 }
 
 static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
-                                                      jint asset)
+                                                      jlong assetHandle)
 {
-    Asset* a = (Asset*)asset;
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
 
     if (a == NULL) {
         jniThrowNullPointerException(env, "asset");
@@ -411,9 +479,9 @@
 }
 
 static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
-                                                               jint asset)
+                                                               jlong assetHandle)
 {
-    Asset* a = (Asset*)asset;
+    Asset* a = reinterpret_cast<Asset*>(assetHandle);
 
     if (a == NULL) {
         jniThrowNullPointerException(env, "asset");
@@ -442,6 +510,25 @@
     return (res) ? static_cast<jint>(cookie) : 0;
 }
 
+static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
+                                                     jstring idmapPath)
+{
+    ScopedUtfChars idmapPath8(env, idmapPath);
+    if (idmapPath8.c_str() == NULL) {
+        return 0;
+    }
+
+    AssetManager* am = assetManagerForJavaObject(env, clazz);
+    if (am == NULL) {
+        return 0;
+    }
+
+    int32_t cookie;
+    bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
+
+    return (res) ? (jint)cookie : 0;
+}
+
 static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
@@ -725,7 +812,11 @@
         }
 #endif
     }
-    return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config) : block;
+    if (block >= 0) {
+        return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
+    }
+
+    return static_cast<jint>(block);
 }
 
 static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
@@ -759,7 +850,7 @@
     res.unlock();
 
     if (block < 0) {
-        return block;
+        return static_cast<jint>(block);
     }
 
     uint32_t ref = ident;
@@ -772,7 +863,11 @@
         }
 #endif
     }
-    return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
+    if (block >= 0) {
+        return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
+    }
+
+    return static_cast<jint>(block);
 }
 
 static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
@@ -784,14 +879,14 @@
     return am->getResources().getTableCount();
 }
 
-static jint android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
+static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
                                                            jint block)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
         return 0;
     }
-    return (jint)am->getResources().getTableStringBlock(block);
+    return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
 }
 
 static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
@@ -810,43 +905,43 @@
     return str;
 }
 
-static jint android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
+static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
         return 0;
     }
-    return (jint)(new ResTable::Theme(am->getResources()));
+    return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
 }
 
 static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
-                                                     jint themeInt)
+                                                     jlong themeHandle)
 {
-    ResTable::Theme* theme = (ResTable::Theme*)themeInt;
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
     delete theme;
 }
 
 static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
-                                                         jint themeInt,
+                                                         jlong themeHandle,
                                                          jint styleRes,
                                                          jboolean force)
 {
-    ResTable::Theme* theme = (ResTable::Theme*)themeInt;
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
     theme->applyStyle(styleRes, force ? true : false);
 }
 
 static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
-                                                   jint destInt, jint srcInt)
+                                                   jlong destHandle, jlong srcHandle)
 {
-    ResTable::Theme* dest = (ResTable::Theme*)destInt;
-    ResTable::Theme* src = (ResTable::Theme*)srcInt;
+    ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
+    ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
     dest->setTo(*src);
 }
 
 static jint android_content_AssetManager_loadThemeAttributeValue(
-    JNIEnv* env, jobject clazz, jint themeInt, jint ident, jobject outValue, jboolean resolve)
+    JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
 {
-    ResTable::Theme* theme = (ResTable::Theme*)themeInt;
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
     const ResTable& res(theme->getResTable());
 
     Res_value value;
@@ -867,10 +962,10 @@
 }
 
 static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
-                                                   jint themeInt, jint pri,
+                                                   jlong themeHandle, jint pri,
                                                    jstring tag, jstring prefix)
 {
-    ResTable::Theme* theme = (ResTable::Theme*)themeInt;
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
     const ResTable& res(theme->getResTable());
 
     // XXX Need to use params.
@@ -878,10 +973,10 @@
 }
 
 static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
-                                                        jint themeToken,
+                                                        jlong themeToken,
                                                         jint defStyleAttr,
                                                         jint defStyleRes,
-                                                        jint xmlParserToken,
+                                                        jlong xmlParserToken,
                                                         jintArray attrs,
                                                         jintArray outValues,
                                                         jintArray outIndices)
@@ -902,9 +997,9 @@
     DEBUG_STYLES(LOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
         themeToken, defStyleAttr, defStyleRes, xmlParserToken));
 
-    ResTable::Theme* theme = (ResTable::Theme*)themeToken;
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
     const ResTable& res = theme->getResTable();
-    ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
     ResTable_config config;
     Res_value value;
 
@@ -1097,7 +1192,7 @@
         dest[STYLE_TYPE] = value.dataType;
         dest[STYLE_DATA] = value.data;
         dest[STYLE_ASSET_COOKIE] =
-            block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
+            block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
         dest[STYLE_DENSITY] = config.density;
@@ -1123,7 +1218,7 @@
 }
 
 static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
-                                                        jint xmlParserToken,
+                                                        jlong xmlParserToken,
                                                         jintArray attrs,
                                                         jintArray outValues,
                                                         jintArray outIndices)
@@ -1240,7 +1335,7 @@
         dest[STYLE_TYPE] = value.dataType;
         dest[STYLE_DATA] = value.data;
         dest[STYLE_ASSET_COOKIE] =
-            block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
+            block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
         dest[STYLE_DENSITY] = config.density;
@@ -1280,7 +1375,7 @@
     ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
     res.unlock();
 
-    return bagOff;
+    return static_cast<jint>(bagOff);
 }
 
 static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
@@ -1352,7 +1447,7 @@
         // Write the final value back to Java.
         dest[STYLE_TYPE] = value.dataType;
         dest[STYLE_DATA] = value.data;
-        dest[STYLE_ASSET_COOKIE] = (jint)res.getTableCookie(block);
+        dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
         dest[STYLE_DENSITY] = config.density;
@@ -1370,7 +1465,7 @@
     return i;
 }
 
-static jint android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
+static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
                                                          jint cookie,
                                                          jstring fileName)
 {
@@ -1405,7 +1500,7 @@
         return 0;
     }
 
-    return (jint)block;
+    return reinterpret_cast<jlong>(block);
 }
 
 static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
@@ -1569,8 +1664,11 @@
     return array;
 }
 
-static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)
+static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
 {
+    if (isSystem) {
+        verifySystemIdmaps();
+    }
     AssetManager* am = new AssetManager();
     if (am == NULL) {
         jniThrowException(env, "java/lang/OutOfMemoryError", "");
@@ -1580,17 +1678,17 @@
     am->addDefaultAssets();
 
     ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
-    env->SetIntField(clazz, gAssetManagerOffsets.mObject, (jint)am);
+    env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
 }
 
 static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
 {
     AssetManager* am = (AssetManager*)
-        (env->GetIntField(clazz, gAssetManagerOffsets.mObject));
+        (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
     ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
     if (am != NULL) {
         delete am;
-        env->SetIntField(clazz, gAssetManagerOffsets.mObject, 0);
+        env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
     }
 }
 
@@ -1624,30 +1722,32 @@
     /* name, signature, funcPtr */
 
     // Basic asset stuff.
-    { "openAsset",      "(Ljava/lang/String;I)I",
+    { "openAsset",      "(Ljava/lang/String;I)J",
         (void*) android_content_AssetManager_openAsset },
     { "openAssetFd",      "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
         (void*) android_content_AssetManager_openAssetFd },
-    { "openNonAssetNative", "(ILjava/lang/String;I)I",
+    { "openNonAssetNative", "(ILjava/lang/String;I)J",
         (void*) android_content_AssetManager_openNonAssetNative },
     { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
         (void*) android_content_AssetManager_openNonAssetFdNative },
     { "list",           "(Ljava/lang/String;)[Ljava/lang/String;",
         (void*) android_content_AssetManager_list },
-    { "destroyAsset",   "(I)V",
+    { "destroyAsset",   "(J)V",
         (void*) android_content_AssetManager_destroyAsset },
-    { "readAssetChar",  "(I)I",
+    { "readAssetChar",  "(J)I",
         (void*) android_content_AssetManager_readAssetChar },
-    { "readAsset",      "(I[BII)I",
+    { "readAsset",      "(J[BII)I",
         (void*) android_content_AssetManager_readAsset },
-    { "seekAsset",      "(IJI)J",
+    { "seekAsset",      "(JJI)J",
         (void*) android_content_AssetManager_seekAsset },
-    { "getAssetLength", "(I)J",
+    { "getAssetLength", "(J)J",
         (void*) android_content_AssetManager_getAssetLength },
-    { "getAssetRemainingLength", "(I)J",
+    { "getAssetRemainingLength", "(J)J",
         (void*) android_content_AssetManager_getAssetRemainingLength },
     { "addAssetPathNative", "(Ljava/lang/String;)I",
         (void*) android_content_AssetManager_addAssetPath },
+    { "addOverlayPath",   "(Ljava/lang/String;)I",
+        (void*) android_content_AssetManager_addOverlayPath },
     { "isUpToDate",     "()Z",
         (void*) android_content_AssetManager_isUpToDate },
 
@@ -1674,27 +1774,27 @@
         (void*) android_content_AssetManager_loadResourceBagValue },
     { "getStringBlockCount","()I",
         (void*) android_content_AssetManager_getStringBlockCount },
-    { "getNativeStringBlock","(I)I",
+    { "getNativeStringBlock","(I)J",
         (void*) android_content_AssetManager_getNativeStringBlock },
     { "getCookieName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getCookieName },
 
     // Themes.
-    { "newTheme", "()I",
+    { "newTheme", "()J",
         (void*) android_content_AssetManager_newTheme },
-    { "deleteTheme", "(I)V",
+    { "deleteTheme", "(J)V",
         (void*) android_content_AssetManager_deleteTheme },
-    { "applyThemeStyle", "(IIZ)V",
+    { "applyThemeStyle", "(JIZ)V",
         (void*) android_content_AssetManager_applyThemeStyle },
-    { "copyTheme", "(II)V",
+    { "copyTheme", "(JJ)V",
         (void*) android_content_AssetManager_copyTheme },
-    { "loadThemeAttributeValue", "(IILandroid/util/TypedValue;Z)I",
+    { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadThemeAttributeValue },
-    { "dumpTheme", "(IILjava/lang/String;Ljava/lang/String;)V",
+    { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
         (void*) android_content_AssetManager_dumpTheme },
-    { "applyStyle","(IIII[I[I[I)Z",
+    { "applyStyle","(JIIJ[I[I[I)Z",
         (void*) android_content_AssetManager_applyStyle },
-    { "retrieveAttributes","(I[I[I[I)Z",
+    { "retrieveAttributes","(J[I[I[I)Z",
         (void*) android_content_AssetManager_retrieveAttributes },
     { "getArraySize","(I)I",
         (void*) android_content_AssetManager_getArraySize },
@@ -1702,7 +1802,7 @@
         (void*) android_content_AssetManager_retrieveArray },
 
     // XML files.
-    { "openXmlAssetNative", "(ILjava/lang/String;)I",
+    { "openXmlAssetNative", "(ILjava/lang/String;)J",
         (void*) android_content_AssetManager_openXmlAssetNative },
 
     // Arrays.
@@ -1714,7 +1814,7 @@
         (void*) android_content_AssetManager_getArrayIntResource },
 
     // Bookkeeping.
-    { "init",           "()V",
+    { "init",           "(Z)V",
         (void*) android_content_AssetManager_init },
     { "destroy",        "()V",
         (void*) android_content_AssetManager_destroy },
@@ -1766,7 +1866,7 @@
     jclass assetManager = env->FindClass("android/content/res/AssetManager");
     LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
     gAssetManagerOffsets.mObject
-        = env->GetFieldID(assetManager, "mObject", "I");
+        = env->GetFieldID(assetManager, "mObject", "J");
     LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
 
     jclass stringClass = env->FindClass("java/lang/String");
diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp
index 463d3c0..f29250f 100644
--- a/core/jni/android_util_StringBlock.cpp
+++ b/core/jni/android_util_StringBlock.cpp
@@ -31,7 +31,7 @@
 
 // ----------------------------------------------------------------------------
 
-static jint android_content_StringBlock_nativeCreate(JNIEnv* env, jobject clazz,
+static jlong android_content_StringBlock_nativeCreate(JNIEnv* env, jobject clazz,
                                                   jbyteArray bArray,
                                                   jint off, jint len)
 {
@@ -56,13 +56,13 @@
         return 0;
     }
 
-    return (jint)osb;
+    return reinterpret_cast<jlong>(osb);
 }
 
 static jint android_content_StringBlock_nativeGetSize(JNIEnv* env, jobject clazz,
-                                                   jint token)
+                                                   jlong token)
 {
-    ResStringPool* osb = (ResStringPool*)token;
+    ResStringPool* osb = reinterpret_cast<ResStringPool*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
@@ -72,9 +72,9 @@
 }
 
 static jstring android_content_StringBlock_nativeGetString(JNIEnv* env, jobject clazz,
-                                                        jint token, jint idx)
+                                                        jlong token, jint idx)
 {
-    ResStringPool* osb = (ResStringPool*)token;
+    ResStringPool* osb = reinterpret_cast<ResStringPool*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
@@ -96,9 +96,9 @@
 }
 
 static jintArray android_content_StringBlock_nativeGetStyle(JNIEnv* env, jobject clazz,
-                                                         jint token, jint idx)
+                                                         jlong token, jint idx)
 {
-    ResStringPool* osb = (ResStringPool*)token;
+    ResStringPool* osb = reinterpret_cast<ResStringPool*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return NULL;
@@ -139,9 +139,9 @@
 }
 
 static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz,
-                                                   jint token)
+                                                   jlong token)
 {
-    ResStringPool* osb = (ResStringPool*)token;
+    ResStringPool* osb = reinterpret_cast<ResStringPool*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return;
@@ -157,15 +157,15 @@
  */
 static JNINativeMethod gStringBlockMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeCreate",      "([BII)I",
+    { "nativeCreate",      "([BII)J",
             (void*) android_content_StringBlock_nativeCreate },
-    { "nativeGetSize",      "(I)I",
+    { "nativeGetSize",      "(J)I",
             (void*) android_content_StringBlock_nativeGetSize },
-    { "nativeGetString",    "(II)Ljava/lang/String;",
+    { "nativeGetString",    "(JI)Ljava/lang/String;",
             (void*) android_content_StringBlock_nativeGetString },
-    { "nativeGetStyle",    "(II)[I",
+    { "nativeGetStyle",    "(JI)[I",
             (void*) android_content_StringBlock_nativeGetStyle },
-    { "nativeDestroy",      "(I)V",
+    { "nativeDestroy",      "(J)V",
             (void*) android_content_StringBlock_nativeDestroy },
 };
 
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index ad6033b..03de5c0 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -31,7 +31,7 @@
 
 // ----------------------------------------------------------------------------
 
-static jint android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz,
+static jlong android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz,
                                                jbyteArray bArray,
                                                jint off, jint len)
 {
@@ -55,25 +55,25 @@
         return 0;
     }
 
-    return (jint)osb;
+    return reinterpret_cast<jlong>(osb);
 }
 
-static jint android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
-                                                       jint token)
+static jlong android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
+                                                       jlong token)
 {
-    ResXMLTree* osb = (ResXMLTree*)token;
+    ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)&osb->getStrings();
+    return reinterpret_cast<jlong>(&osb->getStrings());
 }
 
-static jint android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz,
-                                                          jint token)
+static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz,
+                                                          jlong token)
 {
-    ResXMLTree* osb = (ResXMLTree*)token;
+    ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
@@ -87,19 +87,19 @@
 
     st->restart();
 
-    return (jint)st;
+    return reinterpret_cast<jlong>(st);
 }
 
 static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz,
-                                             jint token)
+                                             jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         return ResXMLParser::END_DOCUMENT;
     }
 
     do {
-        jint code = (jint)st->next();
+        ResXMLParser::event_code_t code = st->next();
         switch (code) {
             case ResXMLParser::START_TAG:
                 return 2;
@@ -123,139 +123,139 @@
 }
 
 static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz,
-                                                   jint token)
+                                                   jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         return -1;
     }
 
-    return (jint)st->getElementNamespaceID();
+    return static_cast<jint>(st->getElementNamespaceID());
 }
 
 static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz,
-                                                jint token)
+                                                jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         return -1;
     }
 
-    return (jint)st->getElementNameID();
+    return static_cast<jint>(st->getElementNameID());
 }
 
 static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz,
-                                                jint token)
+                                                jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         return -1;
     }
 
-    return (jint)st->getTextID();
+    return static_cast<jint>(st->getTextID());
 }
 
 static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz,
-                                                         jint token)
+                                                         jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getLineNumber();
+    return static_cast<jint>(st->getLineNumber());
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz,
-                                                          jint token)
+                                                          jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeCount();
+    return static_cast<jint>(st->getAttributeCount());
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz,
-                                                                 jint token, jint idx)
+                                                                 jlong token, jint idx)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeNamespaceID(idx);
+    return static_cast<jint>(st->getAttributeNamespaceID(idx));
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz,
-                                                         jint token, jint idx)
+                                                         jlong token, jint idx)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeNameID(idx);
+    return static_cast<jint>(st->getAttributeNameID(idx));
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz,
-                                                             jint token, jint idx)
+                                                             jlong token, jint idx)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeNameResID(idx);
+    return static_cast<jint>(st->getAttributeNameResID(idx));
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz,
-                                                                jint token, jint idx)
+                                                                jlong token, jint idx)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeDataType(idx);
+    return static_cast<jint>(st->getAttributeDataType(idx));
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz,
-                                                            jint token, jint idx)
+                                                            jlong token, jint idx)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeData(idx);
+    return static_cast<jint>(st->getAttributeData(idx));
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz,
-                                                                   jint token, jint idx)
+                                                                   jlong token, jint idx)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
-    return (jint)st->getAttributeValueStringID(idx);
+    return static_cast<jint>(st->getAttributeValueStringID(idx));
 }
 
 static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz,
-                                                             jint token,
+                                                             jlong token,
                                                              jstring ns, jstring name)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL || name == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
@@ -271,7 +271,7 @@
     const char16_t* name16 = env->GetStringChars(name, NULL);
     jsize nameLen = env->GetStringLength(name);
 
-    jint idx = (jint)st->indexOfAttribute(ns16, nsLen, name16, nameLen);
+    jint idx = static_cast<jint>(st->indexOfAttribute(ns16, nsLen, name16, nameLen));
 
     if (ns) {
         env->ReleaseStringChars(ns, ns16);
@@ -282,35 +282,35 @@
 }
 
 static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz,
-                                                          jint token)
+                                                          jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
     ssize_t idx = st->indexOfID();
-    return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
+    return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1;
 }
 
 static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz,
-                                                             jint token)
+                                                             jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
     }
 
     ssize_t idx = st->indexOfClass();
-    return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
+    return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1;
 }
 
 static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz,
-                                                             jint token)
+                                                             jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return 0;
@@ -332,9 +332,9 @@
 }
 
 static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz,
-                                                          jint token)
+                                                          jlong token)
 {
-    ResXMLParser* st = (ResXMLParser*)token;
+    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
     if (st == NULL) {
         jniThrowNullPointerException(env, NULL);
         return;
@@ -344,9 +344,9 @@
 }
 
 static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
-                                                   jint token)
+                                                   jlong token)
 {
-    ResXMLTree* osb = (ResXMLTree*)token;
+    ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token);
     if (osb == NULL) {
         jniThrowNullPointerException(env, NULL);
         return;
@@ -362,47 +362,47 @@
  */
 static JNINativeMethod gXmlBlockMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeCreate",               "([BII)I",
+    { "nativeCreate",               "([BII)J",
             (void*) android_content_XmlBlock_nativeCreate },
-    { "nativeGetStringBlock",       "(I)I",
+    { "nativeGetStringBlock",       "(J)J",
             (void*) android_content_XmlBlock_nativeGetStringBlock },
-    { "nativeCreateParseState",     "(I)I",
+    { "nativeCreateParseState",     "(J)J",
             (void*) android_content_XmlBlock_nativeCreateParseState },
-    { "nativeNext",                 "(I)I",
+    { "nativeNext",                 "(J)I",
             (void*) android_content_XmlBlock_nativeNext },
-    { "nativeGetNamespace",         "(I)I",
+    { "nativeGetNamespace",         "(J)I",
             (void*) android_content_XmlBlock_nativeGetNamespace },
-    { "nativeGetName",              "(I)I",
+    { "nativeGetName",              "(J)I",
             (void*) android_content_XmlBlock_nativeGetName },
-    { "nativeGetText",              "(I)I",
+    { "nativeGetText",              "(J)I",
             (void*) android_content_XmlBlock_nativeGetText },
-    { "nativeGetLineNumber",        "(I)I",
+    { "nativeGetLineNumber",        "(J)I",
             (void*) android_content_XmlBlock_nativeGetLineNumber },
-    { "nativeGetAttributeCount",    "(I)I",
+    { "nativeGetAttributeCount",    "(J)I",
             (void*) android_content_XmlBlock_nativeGetAttributeCount },
-    { "nativeGetAttributeNamespace","(II)I",
+    { "nativeGetAttributeNamespace","(JI)I",
             (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
-    { "nativeGetAttributeName",     "(II)I",
+    { "nativeGetAttributeName",     "(JI)I",
             (void*) android_content_XmlBlock_nativeGetAttributeName },
-    { "nativeGetAttributeResource", "(II)I",
+    { "nativeGetAttributeResource", "(JI)I",
             (void*) android_content_XmlBlock_nativeGetAttributeResource },
-    { "nativeGetAttributeDataType", "(II)I",
+    { "nativeGetAttributeDataType", "(JI)I",
             (void*) android_content_XmlBlock_nativeGetAttributeDataType },
-    { "nativeGetAttributeData",    "(II)I",
+    { "nativeGetAttributeData",    "(JI)I",
             (void*) android_content_XmlBlock_nativeGetAttributeData },
-    { "nativeGetAttributeStringValue", "(II)I",
+    { "nativeGetAttributeStringValue", "(JI)I",
             (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
-    { "nativeGetAttributeIndex",    "(ILjava/lang/String;Ljava/lang/String;)I",
+    { "nativeGetAttributeIndex",    "(JLjava/lang/String;Ljava/lang/String;)I",
             (void*) android_content_XmlBlock_nativeGetAttributeIndex },
-    { "nativeGetIdAttribute",      "(I)I",
+    { "nativeGetIdAttribute",      "(J)I",
             (void*) android_content_XmlBlock_nativeGetIdAttribute },
-    { "nativeGetClassAttribute",   "(I)I",
+    { "nativeGetClassAttribute",   "(J)I",
             (void*) android_content_XmlBlock_nativeGetClassAttribute },
-    { "nativeGetStyleAttribute",   "(I)I",
+    { "nativeGetStyleAttribute",   "(J)I",
             (void*) android_content_XmlBlock_nativeGetStyleAttribute },
-    { "nativeDestroyParseState",    "(I)V",
+    { "nativeDestroyParseState",    "(J)V",
             (void*) android_content_XmlBlock_nativeDestroyParseState },
-    { "nativeDestroy",              "(I)V",
+    { "nativeDestroy",              "(J)V",
             (void*) android_content_XmlBlock_nativeDestroy },
 };
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 118af1b..591ff77 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -118,14 +118,12 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
-        jobject graphicBuffer, jintArray atlasMapArray, jint count) {
+        jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
 
     sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
-    jint* atlasMap = env->GetIntArrayElements(atlasMapArray, NULL);
-
-    Caches::getInstance().assetAtlas.init(buffer, atlasMap, count);
-
-    env->ReleaseIntArrayElements(atlasMapArray, atlasMap, 0);
+    jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
+    Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
+    env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -216,9 +214,9 @@
 }
 
 static void android_view_GLES20Canvas_detachFunctor(JNIEnv* env,
-        jobject clazz, jlong rendererHandle, jlong functorHandle) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
-    Functor* functor = reinterpret_cast<Functor*>(functorHandle);
+        jobject clazz, jlong rendererPtr, jlong functorPtr) {
+    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
     renderer->detachFunctor(functor);
 }
 
@@ -1163,7 +1161,7 @@
     { "nInitCaches",        "()Z",             (void*) android_view_GLES20Canvas_initCaches },
     { "nTerminateCaches",   "()V",             (void*) android_view_GLES20Canvas_terminateCaches },
 
-    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[II)V",
+    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[JI)V",
             (void*) android_view_GLES20Canvas_initAtlas },
 
     { "nCreateRenderer",    "()J",             (void*) android_view_GLES20Canvas_createRenderer },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3342bab..c2d4ec0 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -113,7 +113,8 @@
         return NULL;
     }
 
-    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get());
+    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
+            gSurfaceClassInfo.ctor, (jlong)surface.get());
     if (surfaceObj == NULL) {
         if (env->ExceptionCheck()) {
             ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
index 87e339c..609c565 100644
--- a/core/jni/android_view_SurfaceSession.cpp
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -35,22 +35,22 @@
 sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
         JNIEnv* env, jobject surfaceSessionObj) {
     return reinterpret_cast<SurfaceComposerClient*>(
-            env->GetIntField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
+            env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
 }
 
 
-static jint nativeCreate(JNIEnv* env, jclass clazz) {
+static jlong nativeCreate(JNIEnv* env, jclass clazz) {
     SurfaceComposerClient* client = new SurfaceComposerClient();
     client->incStrong((void*)nativeCreate);
-    return reinterpret_cast<jint>(client);
+    return reinterpret_cast<jlong>(client);
 }
 
-static void nativeDestroy(JNIEnv* env, jclass clazz, jint ptr) {
+static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
     SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
     client->decStrong((void*)nativeCreate);
 }
 
-static void nativeKill(JNIEnv* env, jclass clazz, jint ptr) {
+static void nativeKill(JNIEnv* env, jclass clazz, jlong ptr) {
     SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
     client->dispose();
 }
@@ -58,11 +58,11 @@
 
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeCreate", "()I",
+    { "nativeCreate", "()J",
             (void*)nativeCreate },
-    { "nativeDestroy", "(I)V",
+    { "nativeDestroy", "(J)V",
             (void*)nativeDestroy },
-    { "nativeKill", "(I)V",
+    { "nativeKill", "(J)V",
             (void*)nativeKill }
 };
 
@@ -72,7 +72,7 @@
     LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
 
     jclass clazz = env->FindClass("android/view/SurfaceSession");
-    gSurfaceSessionClassInfo.mNativeClient = env->GetFieldID(clazz, "mNativeClient", "I");
+    gSurfaceSessionClassInfo.mNativeClient = env->GetFieldID(clazz, "mNativeClient", "J");
     return 0;
 }
 
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index a0982bd..3035d15 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -50,36 +50,41 @@
 
 static inline EGLDisplay getDisplay(JNIEnv* env, jobject o) {
     if (!o) return EGL_NO_DISPLAY;
-    return (EGLDisplay)env->GetIntField(o, gDisplay_EGLDisplayFieldID);
+    return (EGLDisplay)env->GetLongField(o, gDisplay_EGLDisplayFieldID);
 }
 static inline EGLSurface getSurface(JNIEnv* env, jobject o) {
     if (!o) return EGL_NO_SURFACE;
-    return (EGLSurface)env->GetIntField(o, gSurface_EGLSurfaceFieldID);
+    return (EGLSurface)env->GetLongField(o, gSurface_EGLSurfaceFieldID);
 }
 static inline EGLContext getContext(JNIEnv* env, jobject o) {
     if (!o) return EGL_NO_CONTEXT;
-    return (EGLContext)env->GetIntField(o, gContext_EGLContextFieldID);
+    return (EGLContext)env->GetLongField(o, gContext_EGLContextFieldID);
 }
 static inline EGLConfig getConfig(JNIEnv* env, jobject o) {
     if (!o) return 0;
-    return (EGLConfig)env->GetIntField(o, gConfig_EGLConfigFieldID);
+    return (EGLConfig)env->GetLongField(o, gConfig_EGLConfigFieldID);
 }
+
+static inline jboolean EglBoolToJBool(EGLBoolean eglBool) {
+    return eglBool == EGL_TRUE ? JNI_TRUE : JNI_FALSE;
+}
+
 static void nativeClassInit(JNIEnv *_env, jclass eglImplClass)
 {
     jclass config_class = _env->FindClass("com/google/android/gles_jni/EGLConfigImpl");
     gConfig_class = (jclass) _env->NewGlobalRef(config_class);
-    gConfig_ctorID = _env->GetMethodID(gConfig_class,  "<init>", "(I)V");
-    gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class,  "mEGLConfig",  "I");
+    gConfig_ctorID = _env->GetMethodID(gConfig_class,  "<init>", "(J)V");
+    gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class,  "mEGLConfig",  "J");
 
     jclass display_class = _env->FindClass("com/google/android/gles_jni/EGLDisplayImpl");
-    gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "I");
+    gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "J");
 
     jclass context_class = _env->FindClass("com/google/android/gles_jni/EGLContextImpl");
-    gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "I");
+    gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "J");
 
     jclass surface_class = _env->FindClass("com/google/android/gles_jni/EGLSurfaceImpl");
-    gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "I");
-    gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "I");
+    gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "J");
+    gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "J");
 
     jclass bitmap_class = _env->FindClass("android/graphics/Bitmap");
     gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "J");
@@ -123,7 +128,7 @@
     }
 
     EGLDisplay dpy = getDisplay(_env, display);
-    jboolean success = eglInitialize(dpy, NULL, NULL);
+    EGLBoolean success = eglInitialize(dpy, NULL, NULL);
     if (success && major_minor) {
         int len = _env->GetArrayLength(major_minor);
         if (len) {
@@ -134,7 +139,7 @@
             _env->ReleasePrimitiveArrayCritical(major_minor, base, JNI_ABORT);
         }
     }
-    return success;
+    return EglBoolToJBool(success);
 }
 
 static jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display,
@@ -146,14 +151,14 @@
     }
     EGLDisplay dpy = getDisplay(_env, display);
     EGLContext ctx = getContext(_env, context);
-    jboolean success = JNI_FALSE;
+    EGLBoolean success = EGL_FALSE;
     int len = _env->GetArrayLength(value);
     if (len) {
         jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
         success = eglQueryContext(dpy, ctx, attribute, base);
         _env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
     }
-    return success;
+    return EglBoolToJBool(success);
 }
 
 static jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display,
@@ -166,14 +171,14 @@
     EGLDisplay dpy = getDisplay(_env, display);
     EGLContext sur = getSurface(_env, surface);
 
-    jboolean success = JNI_FALSE;
+    EGLBoolean success = EGL_FALSE;
     int len = _env->GetArrayLength(value);
     if (len) {
         jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
         success = eglQuerySurface(dpy, sur, attribute, base);
         _env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
     }
-    return success;
+    return EglBoolToJBool(success);
 }
 
 static jint jni_getInitCount(JNIEnv *_env, jobject _clazz, jobject display) {
@@ -183,7 +188,7 @@
 }
 
 static jboolean jni_eglReleaseThread(JNIEnv *_env, jobject _this) {
-    return eglReleaseThread();
+    return EglBoolToJBool(eglReleaseThread());
 }
 
 static jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display,
@@ -196,7 +201,7 @@
         return JNI_FALSE;
     }
     EGLDisplay dpy = getDisplay(_env, display);
-    jboolean success = JNI_FALSE;
+    EGLBoolean success = EGL_FALSE;
 
     if (configs == NULL) {
         config_size = 0;
@@ -214,14 +219,14 @@
 
     if (success && configs!=NULL) {
         for (int i=0 ; i<num ; i++) {
-            jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
+            jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i]));
             _env->SetObjectArrayElement(configs, i, obj);
         }
     }
-    return success;
+    return EglBoolToJBool(success);
 }
 
-static jint jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
         jobject config, jobject share_context, jintArray attrib_list) {
     if (display == NULL || config == NULL || share_context == NULL
         || !validAttribList(_env, attrib_list)) {
@@ -234,10 +239,10 @@
     jint* base = beginNativeAttribList(_env, attrib_list);
     EGLContext ctx = eglCreateContext(dpy, cnf, shr, base);
     endNativeAttributeList(_env, attrib_list, base);
-    return (jint)ctx;
+    return reinterpret_cast<jlong>(ctx);
 }
 
-static jint jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
         jobject config, jintArray attrib_list) {
     if (display == NULL || config == NULL
         || !validAttribList(_env, attrib_list)) {
@@ -249,7 +254,7 @@
     jint* base = beginNativeAttribList(_env, attrib_list);
     EGLSurface sur = eglCreatePbufferSurface(dpy, cnf, base);
     endNativeAttributeList(_env, attrib_list, base);
-    return (jint)sur;
+    return reinterpret_cast<jlong>(sur);
 }
 
 static PixelFormat convertPixelFormat(SkBitmap::Config format)
@@ -300,15 +305,15 @@
     endNativeAttributeList(_env, attrib_list, base);
 
     if (sur != EGL_NO_SURFACE) {
-        _env->SetIntField(out_sur, gSurface_EGLSurfaceFieldID, (int)sur);
-        _env->SetIntField(out_sur, gSurface_NativePixelRefFieldID, (int)ref);
+        _env->SetLongField(out_sur, gSurface_EGLSurfaceFieldID, reinterpret_cast<jlong>(sur));
+        _env->SetLongField(out_sur, gSurface_NativePixelRefFieldID, reinterpret_cast<jlong>(ref));
     } else {
         ref->unlockPixels();
         SkSafeUnref(ref);
     }
 }
 
-static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
         jobject config, jobject native_window, jintArray attrib_list) {
     if (display == NULL || config == NULL
         || !validAttribList(_env, attrib_list)) {
@@ -332,15 +337,15 @@
     jint* base = beginNativeAttribList(_env, attrib_list);
     EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
     endNativeAttributeList(_env, attrib_list, base);
-    return (jint)sur;
+    return reinterpret_cast<jlong>(sur);
 }
 
-static jint jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
         jobject config, jobject native_window, jintArray attrib_list) {
     if (display == NULL || config == NULL
         || !validAttribList(_env, attrib_list)) {
         jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
-        return JNI_FALSE;
+        return 0;
     }
     EGLDisplay dpy = getDisplay(_env, display);
     EGLContext cnf = getConfig(_env, config);
@@ -360,7 +365,7 @@
     jint* base = beginNativeAttribList(_env, attrib_list);
     EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
     endNativeAttributeList(_env, attrib_list, base);
-    return (jint)sur;
+    return reinterpret_cast<jlong>(sur);
 }
 
 static jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display,
@@ -372,13 +377,13 @@
     }
     EGLDisplay dpy = getDisplay(_env, display);
     EGLContext cnf = getConfig(_env, config);
-    jboolean success = JNI_FALSE;
+    EGLBoolean success = EGL_FALSE;
     jint localValue;
     success = eglGetConfigAttrib(dpy, cnf, attribute, &localValue);
     if (success) {
         _env->SetIntArrayRegion(value, 0, 1, &localValue);
     }
-    return success;
+    return EglBoolToJBool(success);
 }
 
 static jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display,
@@ -389,7 +394,7 @@
         return JNI_FALSE;
     }
     EGLDisplay dpy = getDisplay(_env, display);
-    jboolean success = JNI_FALSE;
+    EGLBoolean success = EGL_FALSE;
     if (configs == NULL) {
         config_size = 0;
     }
@@ -401,11 +406,11 @@
     }
     if (success && configs) {
         for (int i=0 ; i<num ; i++) {
-            jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
+            jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i]));
             _env->SetObjectArrayElement(configs, i, obj);
         }
     }
-    return success;
+    return EglBoolToJBool(success);
 }
 
 static jint jni_eglGetError(JNIEnv *_env, jobject _this) {
@@ -413,20 +418,20 @@
     return error;
 }
 
-static jint jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) {
-    return (jint)eglGetCurrentContext();
+static jlong jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) {
+    return reinterpret_cast<jlong>(eglGetCurrentContext());
 }
 
-static jint jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) {
-    return (jint)eglGetCurrentDisplay();
+static jlong jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) {
+    return reinterpret_cast<jlong>(eglGetCurrentDisplay());
 }
 
-static jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
+static jlong jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
     if ((readdraw != EGL_READ) && (readdraw != EGL_DRAW)) {
         jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
         return 0;
     }
-    return (jint)eglGetCurrentSurface(readdraw);
+    return reinterpret_cast<jlong>(eglGetCurrentSurface(readdraw));
 }
 
 static jboolean jni_eglDestroyContext(JNIEnv *_env, jobject _this, jobject display, jobject context) {
@@ -436,7 +441,7 @@
     }
     EGLDisplay dpy = getDisplay(_env, display);
     EGLContext ctx = getContext(_env, context);
-    return eglDestroyContext(dpy, ctx);
+    return EglBoolToJBool(eglDestroyContext(dpy, ctx));
 }
 
 static jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface) {
@@ -448,18 +453,18 @@
     EGLSurface sur = getSurface(_env, surface);
 
     if (sur) {
-        SkPixelRef* ref = (SkPixelRef*)(_env->GetIntField(surface,
+        SkPixelRef* ref = (SkPixelRef*)(_env->GetLongField(surface,
                 gSurface_NativePixelRefFieldID));
         if (ref) {
             ref->unlockPixels();
             SkSafeUnref(ref);
         }
     }
-    return eglDestroySurface(dpy, sur);
+    return EglBoolToJBool(eglDestroySurface(dpy, sur));
 }
 
-static jint jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) {
-    return (jint)eglGetDisplay(EGL_DEFAULT_DISPLAY);
+static jlong jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) {
+    return reinterpret_cast<jlong>(eglGetDisplay(EGL_DEFAULT_DISPLAY));
 }
 
 static jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobject draw, jobject read, jobject context) {
@@ -471,7 +476,7 @@
     EGLSurface sdr = getSurface(_env, draw);
     EGLSurface srd = getSurface(_env, read);
     EGLContext ctx = getContext(_env, context);
-    return eglMakeCurrent(dpy, sdr, srd, ctx);
+    return EglBoolToJBool(eglMakeCurrent(dpy, sdr, srd, ctx));
 }
 
 static jstring jni_eglQueryString(JNIEnv *_env, jobject _this, jobject display, jint name) {
@@ -491,7 +496,7 @@
     }
     EGLDisplay dpy = getDisplay(_env, display);
     EGLSurface sur = getSurface(_env, surface);
-    return eglSwapBuffers(dpy, sur);
+    return EglBoolToJBool(eglSwapBuffers(dpy, sur));
 }
 
 static jboolean jni_eglTerminate(JNIEnv *_env, jobject _this, jobject display) {
@@ -500,7 +505,7 @@
         return JNI_FALSE;
     }
     EGLDisplay dpy = getDisplay(_env, display);
-    return eglTerminate(dpy);
+    return EglBoolToJBool(eglTerminate(dpy));
 }
 
 static jboolean jni_eglCopyBuffers(JNIEnv *_env, jobject _this, jobject display,
@@ -514,11 +519,11 @@
 }
 
 static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) {
-    return eglWaitGL();
+    return EglBoolToJBool(eglWaitGL());
 }
 
 static jboolean jni_eglWaitNative(JNIEnv *_env, jobject _this, jint engine, jobject bindTarget) {
-    return eglWaitNative(engine);
+    return EglBoolToJBool(eglWaitNative(engine));
 }
 
 
@@ -540,21 +545,21 @@
 {"eglReleaseThread","()Z", (void*)jni_eglReleaseThread },
 {"getInitCount",    "(" DISPLAY ")I", (void*)jni_getInitCount },
 {"eglChooseConfig", "(" DISPLAY "[I[" CONFIG "I[I)Z", (void*)jni_eglChooseConfig },
-{"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)I", (void*)jni_eglCreateContext },
+{"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)J", (void*)jni_eglCreateContext },
 {"eglGetConfigs",   "(" DISPLAY "[" CONFIG "I[I)Z", (void*)jni_eglGetConfigs },
 {"eglTerminate",    "(" DISPLAY ")Z", (void*)jni_eglTerminate },
 {"eglCopyBuffers",  "(" DISPLAY SURFACE OBJECT ")Z", (void*)jni_eglCopyBuffers },
 {"eglWaitNative",   "(I" OBJECT ")Z", (void*)jni_eglWaitNative },
 {"eglGetError",     "()I", (void*)jni_eglGetError },
 {"eglGetConfigAttrib", "(" DISPLAY CONFIG "I[I)Z", (void*)jni_eglGetConfigAttrib },
-{"_eglGetDisplay",   "(" OBJECT ")I", (void*)jni_eglGetDisplay },
-{"_eglGetCurrentContext",  "()I", (void*)jni_eglGetCurrentContext },
-{"_eglGetCurrentDisplay",  "()I", (void*)jni_eglGetCurrentDisplay },
-{"_eglGetCurrentSurface",  "(I)I", (void*)jni_eglGetCurrentSurface },
-{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)I", (void*)jni_eglCreatePbufferSurface },
+{"_eglGetDisplay",   "(" OBJECT ")J", (void*)jni_eglGetDisplay },
+{"_eglGetCurrentContext",  "()J", (void*)jni_eglGetCurrentContext },
+{"_eglGetCurrentDisplay",  "()J", (void*)jni_eglGetCurrentDisplay },
+{"_eglGetCurrentSurface",  "(I)J", (void*)jni_eglGetCurrentSurface },
+{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)J", (void*)jni_eglCreatePbufferSurface },
 {"_eglCreatePixmapSurface", "(" SURFACE DISPLAY CONFIG OBJECT "[I)V", (void*)jni_eglCreatePixmapSurface },
-{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurface },
-{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurfaceTexture },
+{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurfaceTexture },
 {"eglDestroyContext",      "(" DISPLAY CONTEXT ")Z", (void*)jni_eglDestroyContext },
 {"eglDestroySurface",      "(" DISPLAY SURFACE ")Z", (void*)jni_eglDestroySurface },
 {"eglMakeCurrent",         "(" DISPLAY SURFACE SURFACE CONTEXT")Z", (void*)jni_eglMakeCurrent },
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index b3b0049..7975987 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -129,7 +129,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void *>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -4359,7 +4359,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -4460,7 +4460,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -6099,7 +6099,7 @@
     glNormalPointer(
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -6326,7 +6326,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -6756,7 +6756,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -7196,7 +7196,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -7232,7 +7232,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e7db535..83490dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1088,6 +1088,14 @@
         android:label="@string/permlab_readPhoneState"
         android:description="@string/permdesc_readPhoneState" />
 
+    <!-- Allows read only access to precise phone state.
+         @hide Pending API council approval -->
+    <permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
+        android:permissionGroup="android.permission-group.PHONE_CALLS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_readPrecisePhoneState"
+        android:description="@string/permdesc_readPrecisePhoneState" />
+
     <!-- Allows read access to privileged phone state.
          @hide Used internally. -->
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b20f5ba..4647413 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1777,6 +1777,16 @@
         <attr name="publicKey" />
     </declare-styleable>
 
+    <!-- Attributes relating to resource overlay packages. -->
+    <declare-styleable name="AndroidManifestResourceOverlay" parent="AndroidManifest">
+        <!-- Package name of base package whose resources will be overlaid. -->
+        <attr name="targetPackage" />
+
+        <!-- Load order of overlay package. -->
+        <attr name="priority" />
+
+    </declare-styleable>
+
     <!-- Declaration of an {@link android.content.Intent} object in XML.  May
          also include zero or more {@link #IntentCategory <category> and
          {@link #Extra <extra>} tags. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 986a005..012fb83 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1639,6 +1639,14 @@
       connected by a call.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_readPrecisePhoneState">read precise phone states</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_readPrecisePhoneState">Allows the app to access the precise
+      phone states.  This permission allows the app to determine the real
+      call status, whether a call is active or in the background, call fails,
+      precise data connection status and data connection fails.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_wakeLock" product="tablet">prevent tablet from sleeping</string>
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_wakeLock" product="default">prevent phone from sleeping</string>
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
deleted file mode 100644
index 42b7640..0000000
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-package android.util;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Arrays;
-import junit.framework.TestCase;
-
-public final class JsonReaderTest extends TestCase {
-
-    private static final int READER_BUFFER_SIZE = 1024;
-
-    public void testReadArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true, true]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(true, reader.nextBoolean());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testReadEmptyArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[]"));
-        reader.beginArray();
-        assertFalse(reader.hasNext());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testReadObject() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader(
-                "{\"a\": \"android\", \"b\": \"banana\"}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals("android", reader.nextString());
-        assertEquals("b", reader.nextName());
-        assertEquals("banana", reader.nextString());
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testReadEmptyObject() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{}"));
-        reader.beginObject();
-        assertFalse(reader.hasNext());
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testSkipObject() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader(
-                "{\"a\": { \"c\": [], \"d\": [true, true, {}] }, \"b\": \"banana\"}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        reader.skipValue();
-        assertEquals("b", reader.nextName());
-        reader.skipValue();
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testHelloWorld() throws IOException {
-        String json = "{\n" +
-                "   \"hello\": true,\n" +
-                "   \"foo\": [\"world\"]\n" +
-                "}";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginObject();
-        assertEquals("hello", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-        assertEquals("foo", reader.nextName());
-        reader.beginArray();
-        assertEquals("world", reader.nextString());
-        reader.endArray();
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testNulls() {
-        try {
-            new JsonReader(null);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-    }
-
-    public void testEmptyString() throws IOException {
-        try {
-            new JsonReader(new StringReader("")).beginArray();
-        } catch (IOException expected) {
-        }
-        try {
-            new JsonReader(new StringReader("")).beginObject();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testNoTopLevelObject() throws IOException {
-        try {
-            new JsonReader(new StringReader("true")).nextBoolean();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testCharacterUnescaping() throws IOException {
-        String json = "[\"a\","
-                + "\"a\\\"\","
-                + "\"\\\"\","
-                + "\":\","
-                + "\",\","
-                + "\"\\b\","
-                + "\"\\f\","
-                + "\"\\n\","
-                + "\"\\r\","
-                + "\"\\t\","
-                + "\" \","
-                + "\"\\\\\","
-                + "\"{\","
-                + "\"}\","
-                + "\"[\","
-                + "\"]\","
-                + "\"\\u0000\","
-                + "\"\\u0019\","
-                + "\"\\u20AC\""
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals("a", reader.nextString());
-        assertEquals("a\"", reader.nextString());
-        assertEquals("\"", reader.nextString());
-        assertEquals(":", reader.nextString());
-        assertEquals(",", reader.nextString());
-        assertEquals("\b", reader.nextString());
-        assertEquals("\f", reader.nextString());
-        assertEquals("\n", reader.nextString());
-        assertEquals("\r", reader.nextString());
-        assertEquals("\t", reader.nextString());
-        assertEquals(" ", reader.nextString());
-        assertEquals("\\", reader.nextString());
-        assertEquals("{", reader.nextString());
-        assertEquals("}", reader.nextString());
-        assertEquals("[", reader.nextString());
-        assertEquals("]", reader.nextString());
-        assertEquals("\0", reader.nextString());
-        assertEquals("\u0019", reader.nextString());
-        assertEquals("\u20AC", reader.nextString());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testIntegersWithFractionalPartSpecified() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[1.0,1.0,1.0]"));
-        reader.beginArray();
-        assertEquals(1.0, reader.nextDouble());
-        assertEquals(1, reader.nextInt());
-        assertEquals(1L, reader.nextLong());
-    }
-
-    public void testDoubles() throws IOException {
-        String json = "[-0.0,"
-                + "1.0,"
-                + "1.7976931348623157E308,"
-                + "4.9E-324,"
-                + "0.0,"
-                + "-0.5,"
-                + "2.2250738585072014E-308,"
-                + "3.141592653589793,"
-                + "2.718281828459045,"
-                + "\"1.0\","
-                + "\"011.0\","
-                + "\"NaN\","
-                + "\"Infinity\","
-                + "\"-Infinity\""
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(-0.0, reader.nextDouble());
-        assertEquals(1.0, reader.nextDouble());
-        assertEquals(1.7976931348623157E308, reader.nextDouble());
-        assertEquals(4.9E-324, reader.nextDouble());
-        assertEquals(0.0, reader.nextDouble());
-        assertEquals(-0.5, reader.nextDouble());
-        assertEquals(2.2250738585072014E-308, reader.nextDouble());
-        assertEquals(3.141592653589793, reader.nextDouble());
-        assertEquals(2.718281828459045, reader.nextDouble());
-        assertEquals(1,0, reader.nextDouble());
-        assertEquals(11.0, reader.nextDouble());
-        assertTrue(Double.isNaN(reader.nextDouble()));
-        assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble());
-        assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testLenientDoubles() throws IOException {
-        String json = "["
-                + "011.0,"
-                + "NaN,"
-                + "NAN,"
-                + "Infinity,"
-                + "INFINITY,"
-                + "-Infinity"
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(11.0, reader.nextDouble());
-        assertTrue(Double.isNaN(reader.nextDouble()));
-        try {
-            reader.nextDouble();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals("NAN", reader.nextString());
-        assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble());
-        try {
-            reader.nextDouble();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals("INFINITY", reader.nextString());
-        assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testBufferBoundary() throws IOException {
-        char[] pad = new char[READER_BUFFER_SIZE - 8];
-        Arrays.fill(pad, '5');
-        String json = "[\"" + new String(pad) + "\",33333]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(JsonToken.STRING, reader.peek());
-        assertEquals(new String(pad), reader.nextString());
-        assertEquals(JsonToken.NUMBER, reader.peek());
-        assertEquals(33333, reader.nextInt());
-    }
-
-    public void testTruncatedBufferBoundary() throws IOException {
-        char[] pad = new char[READER_BUFFER_SIZE - 8];
-        Arrays.fill(pad, '5');
-        String json = "[\"" + new String(pad) + "\",33333";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(JsonToken.STRING, reader.peek());
-        assertEquals(new String(pad), reader.nextString());
-        assertEquals(JsonToken.NUMBER, reader.peek());
-        assertEquals(33333, reader.nextInt());
-        try {
-            reader.endArray();
-            fail();
-        } catch (IOException e) {
-        }
-    }
-
-    public void testLongestSupportedNumericLiterals() throws IOException {
-        testLongNumericLiterals(READER_BUFFER_SIZE - 1, JsonToken.NUMBER);
-    }
-
-    public void testLongerNumericLiterals() throws IOException {
-        testLongNumericLiterals(READER_BUFFER_SIZE, JsonToken.STRING);
-    }
-
-    private void testLongNumericLiterals(int length, JsonToken expectedToken) throws IOException {
-        char[] longNumber = new char[length];
-        Arrays.fill(longNumber, '9');
-        longNumber[0] = '1';
-        longNumber[1] = '.';
-
-        String json = "[" + new String(longNumber) + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(expectedToken, reader.peek());
-        assertEquals(2.0d, reader.nextDouble());
-        reader.endArray();
-    }
-
-    public void testLongs() throws IOException {
-        String json = "[0,0,0,"
-                + "1,1,1,"
-                + "-1,-1,-1,"
-                + "-9223372036854775808,"
-                + "9223372036854775807,"
-                + "5.0,"
-                + "1.0e2,"
-                + "\"011\","
-                + "\"5.0\","
-                + "\"1.0e2\""
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(0L, reader.nextLong());
-        assertEquals(0, reader.nextInt());
-        assertEquals(0.0, reader.nextDouble());
-        assertEquals(1L, reader.nextLong());
-        assertEquals(1, reader.nextInt());
-        assertEquals(1.0, reader.nextDouble());
-        assertEquals(-1L, reader.nextLong());
-        assertEquals(-1, reader.nextInt());
-        assertEquals(-1.0, reader.nextDouble());
-        try {
-            reader.nextInt();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals(Long.MIN_VALUE, reader.nextLong());
-        try {
-            reader.nextInt();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals(Long.MAX_VALUE, reader.nextLong());
-        assertEquals(5, reader.nextLong());
-        assertEquals(100, reader.nextLong());
-        assertEquals(11, reader.nextLong());
-        assertEquals(5, reader.nextLong());
-        assertEquals(100, reader.nextLong());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    /**
-     * This test fails because there's no double for 9223372036854775806, and
-     * our long parsing uses Double.parseDouble() for fractional values.
-     */
-    public void testHighPrecisionLong() throws IOException {
-        String json = "[9223372036854775806.000]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(9223372036854775806L, reader.nextLong());
-        reader.endArray();
-    }
-
-    public void testMatchingValidNumbers() throws IOException {
-        String json = "[-1,99,-0,0,0e1,0e+1,0e-1,0E1,0E+1,0E-1,0.0,1.0,-1.0,1.0e0,1.0e+1,1.0e-1]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        for (int i = 0; i < 16; i++) {
-            assertEquals(JsonToken.NUMBER, reader.peek());
-            reader.nextDouble();
-        }
-        reader.endArray();
-    }
-
-    public void testRecognizingInvalidNumbers() throws IOException {
-        String json = "[-00,00,001,+1,1f,0x,0xf,0x0,0f1,0ee1,1..0,1e0.1,1.-01,1.+1,1.0x,1.0+]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        for (int i = 0; i < 16; i++) {
-            assertEquals(JsonToken.STRING, reader.peek());
-            reader.nextString();
-        }
-        reader.endArray();
-    }
-
-    public void testNonFiniteDouble() throws IOException {
-        String json = "[NaN]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        try {
-            reader.nextDouble();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testNumberWithHexPrefix() throws IOException {
-        String json = "[0x11]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        try {
-            reader.nextLong();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testNumberWithOctalPrefix() throws IOException {
-        String json = "[01]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        try {
-            reader.nextInt();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testBooleans() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true,false]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(false, reader.nextBoolean());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testMixedCaseLiterals() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[True,TruE,False,FALSE,NULL,nulL]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(false, reader.nextBoolean());
-        assertEquals(false, reader.nextBoolean());
-        reader.nextNull();
-        reader.nextNull();
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testMissingValue() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextString();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testPrematureEndOfInput() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true,"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testPrematurelyClosed() throws IOException {
-        try {
-            JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
-            reader.beginObject();
-            reader.close();
-            reader.nextName();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-
-        try {
-            JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
-            reader.close();
-            reader.beginObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-
-        try {
-            JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
-            reader.beginObject();
-            reader.nextName();
-            reader.peek();
-            reader.close();
-            reader.nextBoolean();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNextFailuresDoNotAdvance() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
-        reader.beginObject();
-        try {
-            reader.nextString();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextName();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.beginArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.endArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.beginObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.endObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextString();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.nextName();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.beginArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.endArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-        reader.close();
-    }
-
-    public void testStringNullIsNotNull() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[\"null\"]"));
-        reader.beginArray();
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNullLiteralIsNotAString() throws IOException {
-       JsonReader reader = new JsonReader(new StringReader("[null]"));
-        reader.beginArray();
-        try {
-            reader.nextString();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testStrictNameValueSeparator() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("{\"a\"=>true}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientNameValueSeparator() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-
-        reader = new JsonReader(new StringReader("{\"a\"=>true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictComments() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[# comment \n true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[/* comment */ true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientComments() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-
-        reader = new JsonReader(new StringReader("[# comment \n true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-
-        reader = new JsonReader(new StringReader("[/* comment */ true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictUnquotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{a:true}"));
-        reader.beginObject();
-        try {
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientUnquotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{a:true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-    }
-
-    public void testStrictSingleQuotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
-        reader.beginObject();
-        try {
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSingleQuotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-    }
-
-    public void testStrictUnquotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[a]"));
-        reader.beginArray();
-        try {
-            reader.nextString();
-            fail();
-        } catch (MalformedJsonException expected) {
-        }
-    }
-
-    public void testLenientUnquotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[a]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals("a", reader.nextString());
-    }
-
-    public void testStrictSingleQuotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("['a']"));
-        reader.beginArray();
-        try {
-            reader.nextString();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSingleQuotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("['a']"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals("a", reader.nextString());
-    }
-
-    public void testStrictSemicolonDelimitedArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true;true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSemicolonDelimitedArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true;true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictSemicolonDelimitedNameValuePair() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextBoolean();
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSemicolonDelimitedNameValuePair() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-        assertEquals("b", reader.nextName());
-    }
-
-    public void testStrictUnnecessaryArraySeparators() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[,true]"));
-        reader.beginArray();
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[true,]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[,]"));
-        reader.beginArray();
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientUnnecessaryArraySeparators() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        reader.nextNull();
-        assertEquals(true, reader.nextBoolean());
-        reader.endArray();
-
-        reader = new JsonReader(new StringReader("[,true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        reader.nextNull();
-        assertEquals(true, reader.nextBoolean());
-        reader.endArray();
-
-        reader = new JsonReader(new StringReader("[true,]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        reader.nextNull();
-        reader.endArray();
-
-        reader = new JsonReader(new StringReader("[,]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        reader.nextNull();
-        reader.nextNull();
-        reader.endArray();
-    }
-
-    public void testStrictMultipleTopLevelValues() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[] []"));
-        reader.beginArray();
-        reader.endArray();
-        try {
-            reader.peek();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientMultipleTopLevelValues() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[] true {}"));
-        reader.setLenient(true);
-        reader.beginArray();
-        reader.endArray();
-        assertEquals(true, reader.nextBoolean());
-        reader.beginObject();
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testStrictTopLevelValueType() {
-        JsonReader reader = new JsonReader(new StringReader("true"));
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientTopLevelValueType() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("true"));
-        reader.setLenient(true);
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictNonExecutePrefix() {
-        JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
-        try {
-            reader.beginArray();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("\ufeff[]"));
-        reader.beginArray();
-        reader.endArray();
-    }
-
-    public void testBomForbiddenAsOtherCharacterInDocument() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[\ufeff]"));
-        reader.beginArray();
-        try {
-            reader.endArray();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testFailWithPosition() throws IOException {
-        testFailWithPosition("Expected literal value at line 6 column 3",
-                "[\n\n\n\n\n0,}]");
-    }
-
-    public void testFailWithPositionIsOffsetByBom() throws IOException {
-        testFailWithPosition("Expected literal value at line 1 column 4",
-                "\ufeff[0,}]");
-    }
-
-    public void testFailWithPositionGreaterThanBufferSize() throws IOException {
-        String spaces = repeat(' ', 8192);
-        testFailWithPosition("Expected literal value at line 6 column 3",
-                "[\n\n" + spaces + "\n\n\n0,}]");
-    }
-
-    private void testFailWithPosition(String message, String json) throws IOException {
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        reader.nextInt();
-        try {
-            reader.peek();
-            fail();
-        } catch (IOException expected) {
-            assertEquals(message, expected.getMessage());
-        }
-    }
-
-    private String repeat(char c, int count) {
-        char[] array = new char[count];
-        Arrays.fill(array, c);
-        return new String(array);
-    }
-}
diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java
deleted file mode 100644
index 1239a3c..0000000
--- a/core/tests/coretests/src/android/util/JsonWriterTest.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-package android.util;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import junit.framework.TestCase;
-
-public final class JsonWriterTest extends TestCase {
-
-    public void testWrongTopLevelType() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        try {
-            jsonWriter.value("a");
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testTwoNames() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        try {
-            jsonWriter.name("a");
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNameWithoutValue() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        try {
-            jsonWriter.endObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testValueWithoutName() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        try {
-            jsonWriter.value(true);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testMultipleTopLevelValues() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray().endArray();
-        try {
-            jsonWriter.beginArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testBadNestingObject() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.beginObject();
-        try {
-            jsonWriter.endArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testBadNestingArray() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.beginArray();
-        try {
-            jsonWriter.endObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNullName() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        try {
-            jsonWriter.name(null);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-    }
-
-    public void testNullStringValue() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        jsonWriter.value((String) null);
-        jsonWriter.endObject();
-        assertEquals("{\"a\":null}", stringWriter.toString());
-    }
-
-    public void testNonFiniteDoubles() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        try {
-            jsonWriter.value(Double.NaN);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(Double.NEGATIVE_INFINITY);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(Double.POSITIVE_INFINITY);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testNonFiniteBoxedDoubles() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        try {
-            jsonWriter.value(new Double(Double.NaN));
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(new Double(Double.NEGATIVE_INFINITY));
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(new Double(Double.POSITIVE_INFINITY));
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testDoubles() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(-0.0);
-        jsonWriter.value(1.0);
-        jsonWriter.value(Double.MAX_VALUE);
-        jsonWriter.value(Double.MIN_VALUE);
-        jsonWriter.value(0.0);
-        jsonWriter.value(-0.5);
-        jsonWriter.value(Double.MIN_NORMAL);
-        jsonWriter.value(Math.PI);
-        jsonWriter.value(Math.E);
-        jsonWriter.endArray();
-        jsonWriter.close();
-        assertEquals("[-0.0,"
-                + "1.0,"
-                + "1.7976931348623157E308,"
-                + "4.9E-324,"
-                + "0.0,"
-                + "-0.5,"
-                + "2.2250738585072014E-308,"
-                + "3.141592653589793,"
-                + "2.718281828459045]", stringWriter.toString());
-    }
-
-    public void testLongs() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(0);
-        jsonWriter.value(1);
-        jsonWriter.value(-1);
-        jsonWriter.value(Long.MIN_VALUE);
-        jsonWriter.value(Long.MAX_VALUE);
-        jsonWriter.endArray();
-        jsonWriter.close();
-        assertEquals("[0,"
-                + "1,"
-                + "-1,"
-                + "-9223372036854775808,"
-                + "9223372036854775807]", stringWriter.toString());
-    }
-
-    public void testNumbers() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(new BigInteger("0"));
-        jsonWriter.value(new BigInteger("9223372036854775808"));
-        jsonWriter.value(new BigInteger("-9223372036854775809"));
-        jsonWriter.value(new BigDecimal("3.141592653589793238462643383"));
-        jsonWriter.endArray();
-        jsonWriter.close();
-        assertEquals("[0,"
-                + "9223372036854775808,"
-                + "-9223372036854775809,"
-                + "3.141592653589793238462643383]", stringWriter.toString());
-    }
-
-    public void testBooleans() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(true);
-        jsonWriter.value(false);
-        jsonWriter.endArray();
-        assertEquals("[true,false]", stringWriter.toString());
-    }
-
-    public void testNulls() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.nullValue();
-        jsonWriter.endArray();
-        assertEquals("[null]", stringWriter.toString());
-    }
-
-    public void testStrings() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value("a");
-        jsonWriter.value("a\"");
-        jsonWriter.value("\"");
-        jsonWriter.value(":");
-        jsonWriter.value(",");
-        jsonWriter.value("\b");
-        jsonWriter.value("\f");
-        jsonWriter.value("\n");
-        jsonWriter.value("\r");
-        jsonWriter.value("\t");
-        jsonWriter.value(" ");
-        jsonWriter.value("\\");
-        jsonWriter.value("{");
-        jsonWriter.value("}");
-        jsonWriter.value("[");
-        jsonWriter.value("]");
-        jsonWriter.value("\0");
-        jsonWriter.value("\u0019");
-        jsonWriter.endArray();
-        assertEquals("[\"a\","
-                + "\"a\\\"\","
-                + "\"\\\"\","
-                + "\":\","
-                + "\",\","
-                + "\"\\b\","
-                + "\"\\f\","
-                + "\"\\n\","
-                + "\"\\r\","
-                + "\"\\t\","
-                + "\" \","
-                + "\"\\\\\","
-                + "\"{\","
-                + "\"}\","
-                + "\"[\","
-                + "\"]\","
-                + "\"\\u0000\","
-                + "\"\\u0019\"]", stringWriter.toString());
-    }
-
-    public void testUnicodeLineBreaksEscaped() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value("\u2028 \u2029");
-        jsonWriter.endArray();
-        assertEquals("[\"\\u2028 \\u2029\"]", stringWriter.toString());
-    }
-
-    public void testEmptyArray() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.endArray();
-        assertEquals("[]", stringWriter.toString());
-    }
-
-    public void testEmptyObject() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.endObject();
-        assertEquals("{}", stringWriter.toString());
-    }
-
-    public void testObjectsInArrays() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(5);
-        jsonWriter.name("b").value(false);
-        jsonWriter.endObject();
-        jsonWriter.beginObject();
-        jsonWriter.name("c").value(6);
-        jsonWriter.name("d").value(true);
-        jsonWriter.endObject();
-        jsonWriter.endArray();
-        assertEquals("[{\"a\":5,\"b\":false},"
-                + "{\"c\":6,\"d\":true}]", stringWriter.toString());
-    }
-
-    public void testArraysInObjects() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        jsonWriter.beginArray();
-        jsonWriter.value(5);
-        jsonWriter.value(false);
-        jsonWriter.endArray();
-        jsonWriter.name("b");
-        jsonWriter.beginArray();
-        jsonWriter.value(6);
-        jsonWriter.value(true);
-        jsonWriter.endArray();
-        jsonWriter.endObject();
-        assertEquals("{\"a\":[5,false],"
-                + "\"b\":[6,true]}", stringWriter.toString());
-    }
-
-    public void testDeepNestingArrays() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.beginArray();
-        }
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.endArray();
-        }
-        assertEquals("[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]", stringWriter.toString());
-    }
-
-    public void testDeepNestingObjects() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.name("a");
-            jsonWriter.beginObject();
-        }
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.endObject();
-        }
-        jsonWriter.endObject();
-        assertEquals("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
-                + "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{"
-                + "}}}}}}}}}}}}}}}}}}}}}", stringWriter.toString());
-    }
-
-    public void testRepeatedName() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(true);
-        jsonWriter.name("a").value(false);
-        jsonWriter.endObject();
-        // JsonWriter doesn't attempt to detect duplicate names
-        assertEquals("{\"a\":true,\"a\":false}", stringWriter.toString());
-    }
-
-    public void testPrettyPrintObject() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.setIndent("   ");
-
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(true);
-        jsonWriter.name("b").value(false);
-        jsonWriter.name("c").value(5.0);
-        jsonWriter.name("e").nullValue();
-        jsonWriter.name("f").beginArray();
-        jsonWriter.value(6.0);
-        jsonWriter.value(7.0);
-        jsonWriter.endArray();
-        jsonWriter.name("g").beginObject();
-        jsonWriter.name("h").value(8.0);
-        jsonWriter.name("i").value(9.0);
-        jsonWriter.endObject();
-        jsonWriter.endObject();
-
-        String expected = "{\n"
-                + "   \"a\": true,\n"
-                + "   \"b\": false,\n"
-                + "   \"c\": 5.0,\n"
-                + "   \"e\": null,\n"
-                + "   \"f\": [\n"
-                + "      6.0,\n"
-                + "      7.0\n"
-                + "   ],\n"
-                + "   \"g\": {\n"
-                + "      \"h\": 8.0,\n"
-                + "      \"i\": 9.0\n"
-                + "   }\n"
-                + "}";
-        assertEquals(expected, stringWriter.toString());
-    }
-
-    public void testPrettyPrintArray() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.setIndent("   ");
-
-        jsonWriter.beginArray();
-        jsonWriter.value(true);
-        jsonWriter.value(false);
-        jsonWriter.value(5.0);
-        jsonWriter.nullValue();
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(6.0);
-        jsonWriter.name("b").value(7.0);
-        jsonWriter.endObject();
-        jsonWriter.beginArray();
-        jsonWriter.value(8.0);
-        jsonWriter.value(9.0);
-        jsonWriter.endArray();
-        jsonWriter.endArray();
-
-        String expected = "[\n"
-                + "   true,\n"
-                + "   false,\n"
-                + "   5.0,\n"
-                + "   null,\n"
-                + "   {\n"
-                + "      \"a\": 6.0,\n"
-                + "      \"b\": 7.0\n"
-                + "   },\n"
-                + "   [\n"
-                + "      8.0,\n"
-                + "      9.0\n"
-                + "   ]\n"
-                + "]";
-        assertEquals(expected, stringWriter.toString());
-    }
-}
diff --git a/core/tests/overlaytests/OverlayAppFirst/Android.mk b/core/tests/overlaytests/OverlayAppFirst/Android.mk
new file mode 100644
index 0000000..ee991fc
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := com.android.overlaytest.first_app_overlay
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayAppFirst/AndroidManifest.xml b/core/tests/overlaytests/OverlayAppFirst/AndroidManifest.xml
new file mode 100644
index 0000000..ec10bbc
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.overlaytest.first_app_overlay"
+        android:versionCode="1"
+        android:versionName="1.0">
+        <overlay android:targetPackage="com.android.overlaytest" android:priority="1"/>
+</manifest>
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg b/core/tests/overlaytests/OverlayAppFirst/res/drawable-nodpi/drawable.jpg
similarity index 100%
rename from core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg
rename to core/tests/overlaytests/OverlayAppFirst/res/drawable-nodpi/drawable.jpg
Binary files differ
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayAppFirst/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..756b0a3
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum: single overlay.
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/values-sv/config.xml b/core/tests/overlaytests/OverlayAppFirst/res/values-sv/config.xml
new file mode 100644
index 0000000..9cdc73e
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/values-sv/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="matrix_100100">400</integer>
+    <integer name="matrix_100101">400</integer>
+    <integer name="matrix_100110">400</integer>
+    <integer name="matrix_100111">400</integer>
+    <integer name="matrix_101100">400</integer>
+    <integer name="matrix_101101">400</integer>
+    <integer name="matrix_101110">400</integer>
+    <integer name="matrix_101111">400</integer>
+    <integer name="matrix_110100">400</integer>
+    <integer name="matrix_110101">400</integer>
+    <integer name="matrix_110110">400</integer>
+    <integer name="matrix_110111">400</integer>
+    <integer name="matrix_111100">400</integer>
+    <integer name="matrix_111101">400</integer>
+    <integer name="matrix_111110">400</integer>
+    <integer name="matrix_111111">400</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/values/config.xml b/core/tests/overlaytests/OverlayAppFirst/res/values/config.xml
new file mode 100644
index 0000000..972137a
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/values/config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="str">single</string>
+    <string name="str2">single</string>
+    <integer name="matrix_101000">300</integer>
+    <integer name="matrix_101001">300</integer>
+    <integer name="matrix_101010">300</integer>
+    <integer name="matrix_101011">300</integer>
+    <integer name="matrix_101100">300</integer>
+    <integer name="matrix_101101">300</integer>
+    <integer name="matrix_101110">300</integer>
+    <integer name="matrix_101111">300</integer>
+    <integer name="matrix_111000">300</integer>
+    <integer name="matrix_111001">300</integer>
+    <integer name="matrix_111010">300</integer>
+    <integer name="matrix_111011">300</integer>
+    <integer name="matrix_111100">300</integer>
+    <integer name="matrix_111101">300</integer>
+    <integer name="matrix_111110">300</integer>
+    <integer name="matrix_111111">300</integer>
+    <bool name="usually_false">true</bool>
+    <integer-array name="fibonacci">
+        <item>21</item>
+        <item>13</item>
+        <item>8</item>
+        <item>5</item>
+        <item>3</item>
+        <item>2</item>
+        <item>1</item>
+        <item>1</item>
+    </integer-array>
+    <!-- The following integer does not exist in the original package. Idmap
+         generation should therefore ignore it. -->
+    <integer name="integer_not_in_original_package">0</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/xml/integer.xml b/core/tests/overlaytests/OverlayAppFirst/res/xml/integer.xml
new file mode 100644
index 0000000..7f628d9
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="1"/>
diff --git a/core/tests/overlaytests/OverlayAppSecond/Android.mk b/core/tests/overlaytests/OverlayAppSecond/Android.mk
new file mode 100644
index 0000000..87402c43
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := com.android.overlaytest.second_app_overlay
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayAppSecond/AndroidManifest.xml b/core/tests/overlaytests/OverlayAppSecond/AndroidManifest.xml
new file mode 100644
index 0000000..ed49863
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.overlaytest.second_app_overlay"
+        android:versionCode="1"
+        android:versionName="1.0">
+        <overlay android:targetPackage="com.android.overlaytest" android:priority="2"/>
+</manifest>
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayAppSecond/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..613f5b6
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum: multiple overlays.
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/values-sv/config.xml b/core/tests/overlaytests/OverlayAppSecond/res/values-sv/config.xml
new file mode 100644
index 0000000..ec4b6c0
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/values-sv/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="matrix_100001">600</integer>
+    <integer name="matrix_100011">600</integer>
+    <integer name="matrix_100101">600</integer>
+    <integer name="matrix_100111">600</integer>
+    <integer name="matrix_101001">600</integer>
+    <integer name="matrix_101011">600</integer>
+    <integer name="matrix_101101">600</integer>
+    <integer name="matrix_101111">600</integer>
+    <integer name="matrix_110001">600</integer>
+    <integer name="matrix_110011">600</integer>
+    <integer name="matrix_110101">600</integer>
+    <integer name="matrix_110111">600</integer>
+    <integer name="matrix_111001">600</integer>
+    <integer name="matrix_111011">600</integer>
+    <integer name="matrix_111101">600</integer>
+    <integer name="matrix_111111">600</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/values/config.xml b/core/tests/overlaytests/OverlayAppSecond/res/values/config.xml
new file mode 100644
index 0000000..8b07216
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="str">multiple</string>
+    <integer name="matrix_100010">500</integer>
+    <integer name="matrix_100011">500</integer>
+    <integer name="matrix_100110">500</integer>
+    <integer name="matrix_100111">500</integer>
+    <integer name="matrix_101010">500</integer>
+    <integer name="matrix_101011">500</integer>
+    <integer name="matrix_101110">500</integer>
+    <integer name="matrix_101111">500</integer>
+    <integer name="matrix_110010">500</integer>
+    <integer name="matrix_110011">500</integer>
+    <integer name="matrix_110110">500</integer>
+    <integer name="matrix_110111">500</integer>
+    <integer name="matrix_111010">500</integer>
+    <integer name="matrix_111011">500</integer>
+    <integer name="matrix_111110">500</integer>
+    <integer name="matrix_111111">500</integer>
+    <bool name="usually_false">false</bool>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/xml/integer.xml b/core/tests/overlaytests/OverlayAppSecond/res/xml/integer.xml
new file mode 100644
index 0000000..f3370a6
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="2"/>
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index f7f67f6..4767e52 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -5,6 +5,10 @@
 
 LOCAL_PACKAGE_NAME := OverlayTest
 
+LOCAL_DEX_PREOPT := false
+
+LOCAL_MODULE_PATH := $(TARGET_OUT)/app
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayTest/res/drawable-nodpi/drawable.jpg b/core/tests/overlaytests/OverlayTest/res/drawable-nodpi/drawable.jpg
new file mode 100644
index 0000000..a3f14f3
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/drawable-nodpi/drawable.jpg
Binary files differ
diff --git a/core/tests/overlaytests/OverlayTest/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayTest/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..cee7a92
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
diff --git a/core/tests/overlaytests/OverlayTest/res/values-sv/config.xml b/core/tests/overlaytests/OverlayTest/res/values-sv/config.xml
new file mode 100644
index 0000000..891853e
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/values-sv/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="matrix_110000">200</integer>
+    <integer name="matrix_110001">200</integer>
+    <integer name="matrix_110010">200</integer>
+    <integer name="matrix_110011">200</integer>
+    <integer name="matrix_110100">200</integer>
+    <integer name="matrix_110101">200</integer>
+    <integer name="matrix_110110">200</integer>
+    <integer name="matrix_110111">200</integer>
+    <integer name="matrix_111000">200</integer>
+    <integer name="matrix_111001">200</integer>
+    <integer name="matrix_111010">200</integer>
+    <integer name="matrix_111011">200</integer>
+    <integer name="matrix_111100">200</integer>
+    <integer name="matrix_111101">200</integer>
+    <integer name="matrix_111110">200</integer>
+    <integer name="matrix_111111">200</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayTest/res/values/config.xml b/core/tests/overlaytests/OverlayTest/res/values/config.xml
new file mode 100644
index 0000000..c692a26
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/values/config.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="str">none</string>
+    <string name="str2">none</string>
+    <integer name="matrix_100000">100</integer>
+    <integer name="matrix_100001">100</integer>
+    <integer name="matrix_100010">100</integer>
+    <integer name="matrix_100011">100</integer>
+    <integer name="matrix_100100">100</integer>
+    <integer name="matrix_100101">100</integer>
+    <integer name="matrix_100110">100</integer>
+    <integer name="matrix_100111">100</integer>
+    <integer name="matrix_101000">100</integer>
+    <integer name="matrix_101001">100</integer>
+    <integer name="matrix_101010">100</integer>
+    <integer name="matrix_101011">100</integer>
+    <integer name="matrix_101100">100</integer>
+    <integer name="matrix_101101">100</integer>
+    <integer name="matrix_101110">100</integer>
+    <integer name="matrix_101111">100</integer>
+    <integer name="matrix_110000">100</integer>
+    <integer name="matrix_110001">100</integer>
+    <integer name="matrix_110010">100</integer>
+    <integer name="matrix_110011">100</integer>
+    <integer name="matrix_110100">100</integer>
+    <integer name="matrix_110101">100</integer>
+    <integer name="matrix_110110">100</integer>
+    <integer name="matrix_110111">100</integer>
+    <integer name="matrix_111000">100</integer>
+    <integer name="matrix_111001">100</integer>
+    <integer name="matrix_111010">100</integer>
+    <integer name="matrix_111011">100</integer>
+    <integer name="matrix_111100">100</integer>
+    <integer name="matrix_111101">100</integer>
+    <integer name="matrix_111110">100</integer>
+    <integer name="matrix_111111">100</integer>
+    <bool name="usually_false">false</bool>
+    <bool name="always_true">true</bool>
+    <integer-array name="fibonacci">
+        <item>1</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>5</item>
+        <item>8</item>
+        <item>13</item>
+        <item>21</item>
+    </integer-array>
+    <integer-array name="prime_numbers">
+        <item>2</item>
+        <item>3</item>
+        <item>5</item>
+        <item>7</item>
+        <item>11</item>
+        <item>13</item>
+        <item>17</item>
+        <item>19</item>
+    </integer-array>
+</resources>
diff --git a/core/tests/overlaytests/OverlayTest/res/xml/integer.xml b/core/tests/overlaytests/OverlayTest/res/xml/integer.xml
new file mode 100644
index 0000000..9383daa
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="0"/>
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java
index 6211c1c..58b7db9 100644
--- a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java
@@ -2,13 +2,21 @@
 
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
 import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.Xml;
+import java.io.BufferedReader;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.Locale;
 
 public abstract class OverlayBaseTest extends AndroidTestCase {
     private Resources mResources;
-    protected boolean mWithOverlay; // will be set by subclasses
+    protected int mMode; // will be set by subclasses
+    static final protected int MODE_NO_OVERLAY = 0;
+    static final protected int MODE_SINGLE_OVERLAY = 1;
+    static final protected int MODE_MULTIPLE_OVERLAYS = 2;
 
     protected void setUp() {
         mResources = getContext().getResources();
@@ -36,20 +44,82 @@
         mResources.updateConfiguration(config, mResources.getDisplayMetrics());
     }
 
-    private void assertResource(int resId, boolean ewo, boolean ew) throws Throwable {
-        boolean expected = mWithOverlay ? ew : ewo;
+    private boolean getExpected(boolean no, boolean so, boolean mo) {
+        switch (mMode) {
+            case MODE_NO_OVERLAY:
+                return no;
+            case MODE_SINGLE_OVERLAY:
+                return so;
+            case MODE_MULTIPLE_OVERLAYS:
+                return mo;
+            default:
+                fail("Unknown mode!");
+                return no;
+        }
+    }
+
+    private String getExpected(String no, String so, String mo) {
+        switch (mMode) {
+            case MODE_NO_OVERLAY:
+                return no;
+            case MODE_SINGLE_OVERLAY:
+                return so;
+            case MODE_MULTIPLE_OVERLAYS:
+                return mo;
+            default:
+                fail("Unknown mode!");
+                return no;
+        }
+    }
+
+    private int getExpected(int no, int so, int mo) {
+        switch (mMode) {
+            case MODE_NO_OVERLAY:
+                return no;
+            case MODE_SINGLE_OVERLAY:
+                return so;
+            case MODE_MULTIPLE_OVERLAYS:
+                return mo;
+            default:
+                fail("Unknown mode!");
+                return no;
+        }
+    }
+
+    private int[] getExpected(int[] no, int[] so, int[] mo) {
+        switch (mMode) {
+            case MODE_NO_OVERLAY:
+                return no;
+            case MODE_SINGLE_OVERLAY:
+                return so;
+            case MODE_MULTIPLE_OVERLAYS:
+                return mo;
+            default:
+                fail("Unknown mode!");
+                return no;
+        }
+    }
+
+    private void assertResource(int resId, boolean no, boolean so, boolean mo) throws Throwable {
+        boolean expected = getExpected(no, so, mo);
         boolean actual = mResources.getBoolean(resId);
         assertEquals(expected, actual);
     }
 
-    private void assertResource(int resId, String ewo, String ew) throws Throwable {
-        String expected = mWithOverlay ? ew : ewo;
+    private void assertResource(int resId, int no, int so, int mo) throws Throwable {
+        int expected = getExpected(no, so, mo);
+        int actual = mResources.getInteger(resId);
+        assertEquals(expected, actual);
+    }
+
+    private void assertResource(int resId, String no, String so, String mo) throws Throwable {
+        String expected = getExpected(no, so, mo);
         String actual = mResources.getString(resId);
         assertEquals(expected, actual);
     }
 
-    private void assertResource(int resId, int[] ewo, int[] ew) throws Throwable {
-        int[] expected = mWithOverlay ? ew : ewo;
+    private void assertResource(int resId, int[] no, int[] so, int[] mo) throws Throwable {
+        int[] expected = getExpected(no, so, mo);
         int[] actual = mResources.getIntArray(resId);
         assertEquals("length:", expected.length, actual.length);
         for (int i = 0; i < actual.length; ++i) {
@@ -57,62 +127,334 @@
         }
     }
 
+    public void testFrameworkBooleanOverlay() throws Throwable {
+        // config_annoy_dianne has the value:
+        // - true when no overlay exists (MODE_NO_OVERLAY)
+        // - false when a single overlay exists (MODE_SINGLE_OVERLAY)
+        // - false when multiple overlays exists (MODE_MULTIPLE_OVERLAYS)
+        final int resId = com.android.internal.R.bool.config_annoy_dianne;
+        assertResource(resId, true, false, false);
+    }
+
     public void testBooleanOverlay() throws Throwable {
-        // config_automatic_brightness_available has overlay (default config)
-        final int resId = com.android.internal.R.bool.config_automatic_brightness_available;
-        assertResource(resId, false, true);
+        // usually_false has the value:
+        // - false when no overlay exists (MODE_NO_OVERLAY)
+        // - true when a single overlay exists (MODE_SINGLE_OVERLAY)
+        // - false when multiple overlays exists (MODE_MULTIPLE_OVERLAYS)
+        final int resId = R.bool.usually_false;
+        assertResource(resId, false, true, false);
     }
 
     public void testBoolean() throws Throwable {
-        // config_annoy_dianne has no overlay
-        final int resId = com.android.internal.R.bool.config_annoy_dianne;
-        assertResource(resId, true, true);
-    }
-
-    public void testStringOverlay() throws Throwable {
-        // phoneTypeCar has an overlay (default config), which shouldn't shadow
-        // the Swedish translation
-        final int resId = com.android.internal.R.string.phoneTypeCar;
-        setLocale("sv_SE");
-        assertResource(resId, "Bil", "Bil");
-    }
-
-    public void testStringSwedishOverlay() throws Throwable {
-        // phoneTypeWork has overlay (no default config, only for lang=sv)
-        final int resId = com.android.internal.R.string.phoneTypeWork;
-        setLocale("en_US");
-        assertResource(resId, "Work", "Work");
-        setLocale("sv_SE");
-        assertResource(resId, "Arbete", "Jobb");
-    }
-
-    public void testString() throws Throwable {
-        // phoneTypeHome has no overlay
-        final int resId = com.android.internal.R.string.phoneTypeHome;
-        setLocale("en_US");
-        assertResource(resId, "Home", "Home");
-        setLocale("sv_SE");
-        assertResource(resId, "Hem", "Hem");
+        // always_true has no overlay
+        final int resId = R.bool.always_true;
+        assertResource(resId, true, true, true);
     }
 
     public void testIntegerArrayOverlay() throws Throwable {
-        // config_scrollBarrierVibePattern has overlay (default config)
-        final int resId = com.android.internal.R.array.config_scrollBarrierVibePattern;
-        assertResource(resId, new int[]{0, 15, 10, 10}, new int[]{100, 200, 300});
+        // fibonacci has values:
+        // - eight first values of Fibonacci sequence, when no overlay exists (MODE_NO_OVERLAY)
+        // - eight first values of Fibonacci sequence (reversed), for single and multiple overlays
+        //   (MODE_SINGLE_OVERLAY, MODE_MULTIPLE_OVERLAYS)
+        final int resId = R.array.fibonacci;
+        assertResource(resId,
+                new int[]{1, 1, 2, 3, 5, 8, 13, 21},
+                new int[]{21, 13, 8, 5, 3, 2, 1, 1},
+                new int[]{21, 13, 8, 5, 3, 2, 1, 1});
     }
 
     public void testIntegerArray() throws Throwable {
-        // config_virtualKeyVibePattern has no overlay
-        final int resId = com.android.internal.R.array.config_virtualKeyVibePattern;
-        final int[] expected = {0, 10, 20, 30};
-        assertResource(resId, expected, expected);
+        // prime_numbers has no overlay
+        final int resId = R.array.prime_numbers;
+        final int[] expected = {2, 3, 5, 7, 11, 13, 17, 19};
+        assertResource(resId, expected, expected, expected);
     }
 
-    public void testAsset() throws Throwable {
-        // drawable/default_background.jpg has overlay (default config)
-        final int resId = com.android.internal.R.drawable.default_wallpaper;
+    public void testDrawable() throws Throwable {
+        // drawable-nodpi/drawable has overlay (default config)
+        final int resId = R.drawable.drawable;
         int actual = calculateRawResourceChecksum(resId);
-        int expected = mWithOverlay ? 0x000051da : 0x0014ebce;
+        int expected = 0;
+        switch (mMode) {
+            case MODE_NO_OVERLAY:
+                expected = 0x00005665;
+                break;
+            case MODE_SINGLE_OVERLAY:
+            case MODE_MULTIPLE_OVERLAYS:
+                expected = 0x000051da;
+                break;
+            default:
+                fail("Unknown mode " + mMode);
+        }
         assertEquals(expected, actual);
     }
+
+    public void testAppString() throws Throwable {
+        final int resId = R.string.str;
+        assertResource(resId, "none", "single", "multiple");
+    }
+
+    public void testApp2() throws Throwable {
+        final int resId = R.string.str2; // only in base package and first app overlay
+        assertResource(resId, "none", "single", "single");
+    }
+
+    public void testAppXml() throws Throwable {
+        int expected = getExpected(0, 1, 2);
+        int actual = -1;
+        XmlResourceParser parser = mResources.getXml(R.xml.integer);
+        int type = parser.getEventType();
+        while (type != XmlResourceParser.END_DOCUMENT && actual == -1) {
+            if (type == XmlResourceParser.START_TAG && "integer".equals(parser.getName())) {
+                AttributeSet as = Xml.asAttributeSet(parser);
+                actual = as.getAttributeIntValue(null, "value", -1);
+            }
+            type = parser.next();
+        }
+        parser.close();
+        assertEquals(expected, actual);
+    }
+
+    public void testAppRaw() throws Throwable {
+        final int resId = R.raw.lorem_ipsum;
+
+        InputStream input = null;
+        BufferedReader reader = null;
+        String actual = "";
+        try {
+            input = mResources.openRawResource(resId);
+            reader = new BufferedReader(new InputStreamReader(input));
+            actual = reader.readLine();
+        } finally {
+            reader.close();
+            input.close();
+        }
+
+        final String no = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " +
+            "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
+            "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip " +
+            "ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " +
+            "esse cillum dolore eu fugiat nulla pariatur. " +
+            "Excepteur sint occaecat cupidatat non proident, " +
+            "sunt in culpa qui officia deserunt mollit anim id est laborum.";
+        final String so = "Lorem ipsum: single overlay.";
+        final String mo = "Lorem ipsum: multiple overlays.";
+
+        assertEquals(getExpected(no, so, mo), actual);
+    }
+
+    /*
+     * testMatrix* tests
+     *
+     * The naming convention textMatrixABCDEF refers to in which packages and
+     * which configurations a resource is defined (1 if the resource is
+     * defined). If defined, a slot is always given the same value.
+     *
+     * SLOT  PACKAGE           CONFIGURATION  VALUE
+     * A     target package    (default)      100
+     * B     target package    -sv            200
+     * C     OverlayAppFirst   (default)      300
+     * D     OverlayAppFirst   -sv            400
+     * E     OverlayAppSecond  (default)      500
+     * F     OverlayAppSecond  -sv            600
+     *
+     * Example: in testMatrix101110, the base package defines the
+     * R.integer.matrix101110 resource for the default configuration (value
+     * 100), OverlayAppFirst defines it for both default and Swedish
+     * configurations (values 300 and 400, respectively), and OverlayAppSecond
+     * defines it for the default configuration (value 500). If both overlays
+     * are loaded, the expected value after setting the language to Swedish is
+     * 400.
+     */
+    public void testMatrix100000() throws Throwable {
+        final int resId = R.integer.matrix_100000;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 100, 100);
+    }
+
+    public void testMatrix100001() throws Throwable {
+        final int resId = R.integer.matrix_100001;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 100, 600);
+    }
+
+    public void testMatrix100010() throws Throwable {
+        final int resId = R.integer.matrix_100010;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 100, 500);
+    }
+
+    public void testMatrix100011() throws Throwable {
+        final int resId = R.integer.matrix_100011;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 100, 600);
+    }
+
+    public void testMatrix100100() throws Throwable {
+        final int resId = R.integer.matrix_100100;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 400);
+    }
+
+    public void testMatrix100101() throws Throwable {
+        final int resId = R.integer.matrix_100101;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 600);
+    }
+
+    public void testMatrix100110() throws Throwable {
+        final int resId = R.integer.matrix_100110;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 400);
+    }
+
+    public void testMatrix100111() throws Throwable {
+        final int resId = R.integer.matrix_100111;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 600);
+    }
+
+    public void testMatrix101000() throws Throwable {
+        final int resId = R.integer.matrix_101000;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 300, 300);
+    }
+
+    public void testMatrix101001() throws Throwable {
+        final int resId = R.integer.matrix_101001;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 300, 600);
+    }
+
+    public void testMatrix101010() throws Throwable {
+        final int resId = R.integer.matrix_101010;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 300, 500);
+    }
+
+    public void testMatrix101011() throws Throwable {
+        final int resId = R.integer.matrix_101011;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 300, 600);
+    }
+
+    public void testMatrix101100() throws Throwable {
+        final int resId = R.integer.matrix_101100;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 400);
+    }
+
+    public void testMatrix101101() throws Throwable {
+        final int resId = R.integer.matrix_101101;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 600);
+    }
+
+    public void testMatrix101110() throws Throwable {
+        final int resId = R.integer.matrix_101110;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 400);
+    }
+
+    public void testMatrix101111() throws Throwable {
+        final int resId = R.integer.matrix_101111;
+        setLocale("sv_SE");
+        assertResource(resId, 100, 400, 600);
+    }
+
+    public void testMatrix110000() throws Throwable {
+        final int resId = R.integer.matrix_110000;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 200);
+    }
+
+    public void testMatrix110001() throws Throwable {
+        final int resId = R.integer.matrix_110001;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 600);
+    }
+
+    public void testMatrix110010() throws Throwable {
+        final int resId = R.integer.matrix_110010;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 200);
+    }
+
+    public void testMatrix110011() throws Throwable {
+        final int resId = R.integer.matrix_110011;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 600);
+    }
+
+    public void testMatrix110100() throws Throwable {
+        final int resId = R.integer.matrix_110100;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 400);
+    }
+
+    public void testMatrix110101() throws Throwable {
+        final int resId = R.integer.matrix_110101;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 600);
+    }
+
+    public void testMatrix110110() throws Throwable {
+        final int resId = R.integer.matrix_110110;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 400);
+    }
+
+    public void testMatrix110111() throws Throwable {
+        final int resId = R.integer.matrix_110111;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 600);
+    }
+
+    public void testMatrix111000() throws Throwable {
+        final int resId = R.integer.matrix_111000;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 200);
+    }
+
+    public void testMatrix111001() throws Throwable {
+        final int resId = R.integer.matrix_111001;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 600);
+    }
+
+    public void testMatrix111010() throws Throwable {
+        final int resId = R.integer.matrix_111010;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 200);
+    }
+
+    public void testMatrix111011() throws Throwable {
+        final int resId = R.integer.matrix_111011;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 200, 600);
+    }
+
+    public void testMatrix111100() throws Throwable {
+        final int resId = R.integer.matrix_111100;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 400);
+    }
+
+    public void testMatrix111101() throws Throwable {
+        final int resId = R.integer.matrix_111101;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 600);
+    }
+
+    public void testMatrix111110() throws Throwable {
+        final int resId = R.integer.matrix_111110;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 400);
+    }
+
+    public void testMatrix111111() throws Throwable {
+        final int resId = R.integer.matrix_111111;
+        setLocale("sv_SE");
+        assertResource(resId, 200, 400, 600);
+    }
 }
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java
new file mode 100644
index 0000000..e104f5a
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java
@@ -0,0 +1,7 @@
+package com.android.overlaytest;
+
+public class WithMultipleOverlaysTest extends OverlayBaseTest {
+    public WithMultipleOverlaysTest() {
+        mMode = MODE_MULTIPLE_OVERLAYS;
+    }
+}
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java
index 1292d03..816a476 100644
--- a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java
@@ -2,6 +2,6 @@
 
 public class WithOverlayTest extends OverlayBaseTest {
     public WithOverlayTest() {
-        mWithOverlay = true;
+        mMode = MODE_SINGLE_OVERLAY;
     }
 }
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java
index 630ff8f..318cccc 100644
--- a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java
@@ -2,6 +2,6 @@
 
 public class WithoutOverlayTest extends OverlayBaseTest {
     public WithoutOverlayTest() {
-        mWithOverlay = false;
+        mMode = MODE_NO_OVERLAY;
     }
 }
diff --git a/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml b/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml
index bcbb0d1..f8b6c7b 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml
+++ b/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml
@@ -2,5 +2,5 @@
         package="com.android.overlaytest.overlay"
         android:versionCode="1"
         android:versionName="1.0">
-    <overlay-package android:name="android"/>
+        <overlay android:targetPackage="android" android:priority="1"/>
 </manifest>
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml b/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml
deleted file mode 100644
index bc52367..0000000
--- a/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="phoneTypeWork">Jobb</string>
-</resources>
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml b/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml
index 794f475..c1e3de1 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml
+++ b/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml
@@ -1,13 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <bool name="config_automatic_brightness_available">true</bool>
-    <string name="phoneTypeCar">Automobile</string>
-    <integer-array name="config_scrollBarrierVibePattern">
-        <item>100</item>
-        <item>200</item>
-        <item>300</item>
-    </integer-array>
-    <!-- The following integer does not exist in the original package. Idmap
-         generation should therefore ignore it. -->
-    <integer name="integer_not_in_original_package">0</integer>
+    <bool name="config_annoy_dianne">false</bool>
 </resources>
diff --git a/core/tests/overlaytests/README b/core/tests/overlaytests/README
deleted file mode 100644
index 4b3e6f2..0000000
--- a/core/tests/overlaytests/README
+++ /dev/null
@@ -1,15 +0,0 @@
-Unit tests for runtime resource overlay
-=======================================
-
-As of this writing, runtime resource overlay is only triggered for
-/system/framework/framework-res.apk. Because of this, installation of
-overlay packages require the Android platform be rebooted. However, the
-regular unit tests (triggered via development/testrunner/runtest.py)
-cannot handle reboots. As a workaround, this directory contains a shell
-script which will trigger the tests in a non-standard way.
-
-Once runtime resource overlay may be applied to applications, the tests
-in this directory should be moved to core/tests/coretests. Also, by
-applying runtime resource overlay to a dedicated test application, the
-test cases would not need to assume default values for non-overlaid
-resources.
diff --git a/core/tests/overlaytests/runtests.sh b/core/tests/overlaytests/runtests.sh
deleted file mode 100755
index 0a721ad40..0000000
--- a/core/tests/overlaytests/runtests.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/bash
-
-adb="adb"
-if [[ $# -gt 0 ]]; then
-	adb="adb $*" # for setting -e, -d or -s <serial>
-fi
-
-function atexit()
-{
-	local retval=$?
-
-	if [[ $retval -eq 0 ]]; then
-		rm $log
-	else
-		echo "There were errors, please check log at $log"
-	fi
-}
-
-log=$(mktemp)
-trap "atexit" EXIT
-
-function compile_module()
-{
-	local android_mk="$1"
-
-	echo "Compiling .${android_mk:${#PWD}}"
-	ONE_SHOT_MAKEFILE="$android_mk" make -C "../../../../../" files | tee -a $log
-	if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
-		exit 1
-	fi
-}
-
-function wait_for_boot_completed()
-{
-	echo "Rebooting device"
-	$adb wait-for-device logcat -c
-	$adb wait-for-device logcat | grep -m 1 -e 'PowerManagerService.*bootCompleted' >/dev/null
-}
-
-function mkdir_if_needed()
-{
-	local path="$1"
-
-	if [[ "${path:0:1}" != "/" ]]; then
-		echo "mkdir_if_needed: error: path '$path' does not begin with /" | tee -a $log
-		exit 1
-	fi
-
-	local basename=$(basename "$path")
-	local dirname=$(dirname "$path")
-	local t=$($adb shell ls -l $dirname | tr -d '\r' | grep -e "${basename}$" | grep -oe '^.')
-
-	case "$t" in
-		d) # File exists, and is a directory ...
-			# do nothing
-			;;
-		l) # ... (or symbolic link possibly to a directory).
-			# do nothing
-			;;
-		"") # File does not exist.
-			mkdir_if_needed "$dirname"
-			$adb shell mkdir "$path"
-			;;
-		*) # File exists, but is not a directory.
-			echo "mkdir_if_needed: file '$path' exists, but is not a directory" | tee -a $log
-			exit 1
-			;;
-	esac
-}
-
-function disable_overlay()
-{
-	echo "Disabling overlay"
-	$adb shell rm /vendor/overlay/framework/framework-res.apk
-	$adb shell rm /data/resource-cache/vendor@overlay@framework@framework-res.apk@idmap
-}
-
-function enable_overlay()
-{
-	echo "Enabling overlay"
-	mkdir_if_needed "/system/vendor"
-	mkdir_if_needed "/vendor/overlay/framework"
-	$adb shell ln -s /data/app/com.android.overlaytest.overlay.apk /vendor/overlay/framework/framework-res.apk
-}
-
-function instrument()
-{
-	local class="$1"
-
-	echo "Instrumenting $class"
-	$adb shell am instrument -w -e class $class com.android.overlaytest/android.test.InstrumentationTestRunner | tee -a $log
-}
-
-function remount()
-{
-	echo "Remounting file system writable"
-	$adb remount | tee -a $log
-}
-
-function sync()
-{
-	echo "Syncing to device"
-	$adb sync data | tee -a $log
-}
-
-# some commands require write access, remount once and for all
-remount
-
-# build and sync
-compile_module "$PWD/OverlayTest/Android.mk"
-compile_module "$PWD/OverlayTestOverlay/Android.mk"
-sync
-
-# instrument test (without overlay)
-$adb shell stop
-disable_overlay
-$adb shell start
-wait_for_boot_completed
-instrument "com.android.overlaytest.WithoutOverlayTest"
-
-# instrument test (with overlay)
-$adb shell stop
-enable_overlay
-$adb shell start
-wait_for_boot_completed
-instrument "com.android.overlaytest.WithOverlayTest"
-
-# cleanup
-exit $(grep -c -e '^FAILURES' $log)
diff --git a/core/tests/overlaytests/testrunner.py b/core/tests/overlaytests/testrunner.py
new file mode 100755
index 0000000..4f94373
--- /dev/null
+++ b/core/tests/overlaytests/testrunner.py
@@ -0,0 +1,679 @@
+#!/usr/bin/python
+import hashlib
+import optparse
+import os
+import re
+import shlex
+import subprocess
+import sys
+import threading
+import time
+
+TASK_COMPILATION = 'compile'
+TASK_DISABLE_OVERLAYS = 'disable overlays'
+TASK_ENABLE_MULTIPLE_OVERLAYS = 'enable multiple overlays'
+TASK_ENABLE_SINGLE_OVERLAY = 'enable single overlay'
+TASK_FILE_EXISTS_TEST = 'test (file exists)'
+TASK_GREP_IDMAP_TEST = 'test (grep idmap)'
+TASK_MD5_TEST = 'test (md5)'
+TASK_IDMAP_PATH = 'idmap --path'
+TASK_IDMAP_SCAN = 'idmap --scan'
+TASK_INSTRUMENTATION = 'instrumentation'
+TASK_INSTRUMENTATION_TEST = 'test (instrumentation)'
+TASK_MKDIR = 'mkdir'
+TASK_PUSH = 'push'
+TASK_ROOT = 'root'
+TASK_REMOUNT = 'remount'
+TASK_RM = 'rm'
+TASK_SETUP_IDMAP_PATH = 'setup idmap --path'
+TASK_SETUP_IDMAP_SCAN = 'setup idmap --scan'
+TASK_START = 'start'
+TASK_STOP = 'stop'
+
+adb = 'adb'
+
+def _adb_shell(cmd):
+    argv = shlex.split(adb + " shell '" + cmd + "; echo $?'")
+    proc = subprocess.Popen(argv, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    (stdout, stderr) = proc.communicate()
+    (stdout, stderr) = (stdout.replace('\r', ''), stderr.replace('\r', ''))
+    tmp = stdout.rsplit('\n', 2)
+    if len(tmp) == 2:
+        stdout == ''
+        returncode = int(tmp[0])
+    else:
+        stdout = tmp[0] + '\n'
+        returncode = int(tmp[1])
+    return returncode, stdout, stderr
+
+class VerbosePrinter:
+    class Ticker(threading.Thread):
+        def _print(self):
+            s = '\r' + self.text + '[' + '.' * self.i + ' ' * (4 - self.i) + ']'
+            sys.stdout.write(s)
+            sys.stdout.flush()
+            self.i = (self.i + 1) % 5
+
+        def __init__(self, cond_var, text):
+            threading.Thread.__init__(self)
+            self.text = text
+            self.setDaemon(True)
+            self.cond_var = cond_var
+            self.running = False
+            self.i = 0
+            self._print()
+            self.running = True
+
+        def run(self):
+            self.cond_var.acquire()
+            while True:
+                self.cond_var.wait(0.25)
+                running = self.running
+                if not running:
+                    break
+                self._print()
+            self.cond_var.release()
+
+        def stop(self):
+            self.cond_var.acquire()
+            self.running = False
+            self.cond_var.notify_all()
+            self.cond_var.release()
+
+    def _start_ticker(self):
+        self.ticker = VerbosePrinter.Ticker(self.cond_var, self.text)
+        self.ticker.start()
+
+    def _stop_ticker(self):
+        self.ticker.stop()
+        self.ticker.join()
+        self.ticker = None
+
+    def _format_begin(self, type, name):
+        N = self.width - len(type) - len(' [    ] ')
+        fmt = '%%s %%-%ds ' % N
+        return fmt % (type, name)
+
+    def __init__(self, use_color):
+        self.cond_var = threading.Condition()
+        self.ticker = None
+        if use_color:
+            self.color_RED = '\033[1;31m'
+            self.color_red = '\033[0;31m'
+            self.color_reset = '\033[0;37m'
+        else:
+            self.color_RED = ''
+            self.color_red = ''
+            self.color_reset = ''
+
+        argv = shlex.split('stty size') # get terminal width
+        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        (stdout, stderr) = proc.communicate()
+        if proc.returncode == 0:
+            (h, w) = stdout.split()
+            self.width = int(w)
+        else:
+            self.width = 72 # conservative guesstimate
+
+    def begin(self, type, name):
+        self.text = self._format_begin(type, name)
+        sys.stdout.write(self.text + '[    ]')
+        sys.stdout.flush()
+        self._start_ticker()
+
+    def end_pass(self, type, name):
+        self._stop_ticker()
+        sys.stdout.write('\r' + self.text + '[ OK ]\n')
+        sys.stdout.flush()
+
+    def end_fail(self, type, name, msg):
+        self._stop_ticker()
+        sys.stdout.write('\r' + self.color_RED + self.text + '[FAIL]\n')
+        sys.stdout.write(self.color_red)
+        sys.stdout.write(msg)
+        sys.stdout.write(self.color_reset)
+        sys.stdout.flush()
+
+class QuietPrinter:
+    def begin(self, type, name):
+        pass
+
+    def end_pass(self, type, name):
+        sys.stdout.write('PASS ' + type + ' ' + name + '\n')
+        sys.stdout.flush()
+
+    def end_fail(self, type, name, msg):
+        sys.stdout.write('FAIL ' + type + ' ' + name + '\n')
+        sys.stdout.flush()
+
+class CompilationTask:
+    def __init__(self, makefile):
+        self.makefile = makefile
+
+    def get_type(self):
+        return TASK_COMPILATION
+
+    def get_name(self):
+        return self.makefile
+
+    def execute(self):
+        os.putenv('ONE_SHOT_MAKEFILE', os.getcwd() + "/" + self.makefile)
+        argv = shlex.split('make -C "../../../../../" files')
+        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        (stdout, stderr) = proc.communicate()
+        return proc.returncode, stdout, stderr
+
+class InstrumentationTask:
+    def __init__(self, instrumentation_class):
+        self.instrumentation_class = instrumentation_class
+
+    def get_type(self):
+        return TASK_INSTRUMENTATION
+
+    def get_name(self):
+        return self.instrumentation_class
+
+    def execute(self):
+        return _adb_shell('am instrument -r -w -e class %s com.android.overlaytest/android.test.InstrumentationTestRunner' % self.instrumentation_class)
+
+class PushTask:
+    def __init__(self, src, dest):
+        self.src = src
+        self.dest = dest
+
+    def get_type(self):
+        return TASK_PUSH
+
+    def get_name(self):
+        return "%s -> %s" % (self.src, self.dest)
+
+    def execute(self):
+        src = os.getenv('OUT') + "/" + self.src
+        argv = shlex.split(adb + ' push %s %s' % (src, self.dest))
+        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        (stdout, stderr) = proc.communicate()
+        return proc.returncode, stdout, stderr
+
+class MkdirTask:
+    def __init__(self, path):
+        self.path = path
+
+    def get_type(self):
+        return TASK_MKDIR
+
+    def get_name(self):
+        return self.path
+
+    def execute(self):
+        return _adb_shell('mkdir -p %s' % self.path)
+
+class RmTask:
+    def __init__(self, path):
+        self.path = path
+
+    def get_type(self):
+        return TASK_RM
+
+    def get_name(self):
+        return self.path
+
+    def execute(self):
+        returncode, stdout, stderr = _adb_shell('ls %s' % self.path)
+        if returncode != 0 and stdout.endswith(': No such file or directory\n'):
+            return 0, "", ""
+        return _adb_shell('rm -r %s' % self.path)
+
+class IdmapPathTask:
+    def __init__(self, path_target_apk, path_overlay_apk, path_idmap):
+        self.path_target_apk = path_target_apk
+        self.path_overlay_apk = path_overlay_apk
+        self.path_idmap = path_idmap
+
+    def get_type(self):
+        return TASK_IDMAP_PATH
+
+    def get_name(self):
+        return self.path_idmap
+
+    def execute(self):
+        return _adb_shell('su system idmap --path "%s" "%s" "%s"' % (self.path_target_apk, self.path_overlay_apk, self.path_idmap))
+
+class IdmapScanTask:
+    def __init__(self, overlay_dir, target_pkg_name, target_pkg, idmap_dir, symlink_dir):
+        self.overlay_dir = overlay_dir
+        self.target_pkg_name = target_pkg_name
+        self.target_pkg = target_pkg
+        self.idmap_dir = idmap_dir
+        self.symlink_dir = symlink_dir
+
+    def get_type(self):
+        return TASK_IDMAP_SCAN
+
+    def get_name(self):
+        return self.target_pkg_name
+
+    def execute(self):
+        return _adb_shell('su system idmap --scan "%s" "%s" "%s" "%s"' % (self.overlay_dir, self.target_pkg_name, self.target_pkg, self.idmap_dir))
+
+class FileExistsTest:
+    def __init__(self, path):
+        self.path = path
+
+    def get_type(self):
+        return TASK_FILE_EXISTS_TEST
+
+    def get_name(self):
+        return self.path
+
+    def execute(self):
+        return _adb_shell('ls %s' % self.path)
+
+class GrepIdmapTest:
+    def __init__(self, path_idmap, pattern, expected_n):
+        self.path_idmap = path_idmap
+        self.pattern = pattern
+        self.expected_n = expected_n
+
+    def get_type(self):
+        return TASK_GREP_IDMAP_TEST
+
+    def get_name(self):
+        return self.pattern
+
+    def execute(self):
+        returncode, stdout, stderr = _adb_shell('idmap --inspect %s' % self.path_idmap)
+        if returncode != 0:
+            return returncode, stdout, stderr
+        all_matches = re.findall('\s' + self.pattern + '$', stdout, flags=re.MULTILINE)
+        if len(all_matches) != self.expected_n:
+            return 1, 'pattern=%s idmap=%s expected=%d found=%d\n' % (self.pattern, self.path_idmap, self.expected_n, len(all_matches)), ''
+        return 0, "", ""
+
+class Md5Test:
+    def __init__(self, path, expected_content):
+        self.path = path
+        self.expected_md5 = hashlib.md5(expected_content).hexdigest()
+
+    def get_type(self):
+        return TASK_MD5_TEST
+
+    def get_name(self):
+        return self.path
+
+    def execute(self):
+        returncode, stdout, stderr = _adb_shell('md5 %s' % self.path)
+        if returncode != 0:
+            return returncode, stdout, stderr
+        actual_md5 = stdout.split()[0]
+        if actual_md5 != self.expected_md5:
+            return 1, 'expected %s, got %s\n' % (self.expected_md5, actual_md5), ''
+        return 0, "", ""
+
+class StartTask:
+    def get_type(self):
+        return TASK_START
+
+    def get_name(self):
+        return ""
+
+    def execute(self):
+        (returncode, stdout, stderr) = _adb_shell('start')
+        if returncode != 0:
+            return returncode, stdout, stderr
+
+        while True:
+            (returncode, stdout, stderr) = _adb_shell('getprop dev.bootcomplete')
+            if returncode != 0:
+                return returncode, stdout, stderr
+            if stdout.strip() == "1":
+                break
+            time.sleep(0.5)
+
+        return 0, "", ""
+
+class StopTask:
+    def get_type(self):
+        return TASK_STOP
+
+    def get_name(self):
+        return ""
+
+    def execute(self):
+        (returncode, stdout, stderr) = _adb_shell('stop')
+        if returncode != 0:
+            return returncode, stdout, stderr
+        return _adb_shell('setprop dev.bootcomplete 0')
+
+class RootTask:
+    def get_type(self):
+        return TASK_ROOT
+
+    def get_name(self):
+        return ""
+
+    def execute(self):
+        (returncode, stdout, stderr) = _adb_shell('getprop service.adb.root 0')
+        if returncode != 0:
+            return returncode, stdout, stderr
+        if stdout.strip() == '1': # already root
+            return 0, "", ""
+
+        argv = shlex.split(adb + ' root')
+        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        (stdout, stderr) = proc.communicate()
+        if proc.returncode != 0:
+            return proc.returncode, stdout, stderr
+
+        argv = shlex.split(adb + ' wait-for-device')
+        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        (stdout, stderr) = proc.communicate()
+        return proc.returncode, stdout, stderr
+
+class RemountTask:
+    def get_type(self):
+        return TASK_REMOUNT
+
+    def get_name(self):
+        return ""
+
+    def execute(self):
+        argv = shlex.split(adb + ' remount')
+        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        (stdout, stderr) = proc.communicate()
+        # adb remount returns 0 even if the operation failed, so check stdout
+        if stdout.startswith('remount failed:'):
+            return 1, stdout, stderr
+        return proc.returncode, stdout, stderr
+
+class CompoundTask:
+    def __init__(self, type, tasks):
+        self.type = type
+        self.tasks = tasks
+
+    def get_type(self):
+        return self.type
+
+    def get_name(self):
+        return ""
+
+    def execute(self):
+        for t in self.tasks:
+            (returncode, stdout, stderr) = t.execute()
+            if returncode != 0:
+                return returncode, stdout, stderr
+        return 0, "", ""
+
+def _create_disable_overlays_task():
+    tasks = [
+        RmTask("/vendor/overlay/framework_a.apk"),
+        RmTask("/vendor/overlay/framework_b.apk"),
+        RmTask("/data/resource-cache/vendor@overlay@framework_a.apk@idmap"),
+        RmTask("/data/resource-cache/vendor@overlay@framework_b.apk@idmap"),
+        RmTask("/vendor/overlay/app_a.apk"),
+        RmTask("/vendor/overlay/app_b.apk"),
+        RmTask("/data/resource-cache/vendor@overlay@app_a.apk@idmap"),
+        RmTask("/data/resource-cache/vendor@overlay@app_b.apk@idmap"),
+    ]
+    return CompoundTask(TASK_DISABLE_OVERLAYS, tasks)
+
+def _create_enable_single_overlay_task():
+    tasks = [
+        _create_disable_overlays_task(),
+        MkdirTask('/system/vendor'),
+        MkdirTask('/vendor/overlay'),
+        PushTask('/data/app/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_a.apk'),
+        PushTask('/data/app/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
+    ]
+    return CompoundTask(TASK_ENABLE_SINGLE_OVERLAY, tasks)
+
+def _create_enable_multiple_overlays_task():
+    tasks = [
+        _create_disable_overlays_task(),
+        MkdirTask('/system/vendor'),
+        MkdirTask('/vendor/overlay'),
+
+        PushTask('/data/app/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_b.apk'),
+        PushTask('/data/app/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
+        PushTask('/data/app/com.android.overlaytest.second_app_overlay.apk', '/vendor/overlay/app_b.apk'),
+    ]
+    return CompoundTask(TASK_ENABLE_MULTIPLE_OVERLAYS, tasks)
+
+def _create_setup_idmap_path_task(idmaps, symlinks):
+    tasks = [
+        _create_enable_single_overlay_task(),
+        RmTask(symlinks),
+        RmTask(idmaps),
+        MkdirTask(idmaps),
+        MkdirTask(symlinks),
+    ]
+    return CompoundTask(TASK_SETUP_IDMAP_PATH, tasks)
+
+def _create_setup_idmap_scan_task(idmaps, symlinks):
+    tasks = [
+        _create_enable_single_overlay_task(),
+        RmTask(symlinks),
+        RmTask(idmaps),
+        MkdirTask(idmaps),
+        MkdirTask(symlinks),
+        _create_enable_multiple_overlays_task(),
+    ]
+    return CompoundTask(TASK_SETUP_IDMAP_SCAN, tasks)
+
+def _handle_instrumentation_task_output(stdout, printer):
+    regex_status_code = re.compile(r'^INSTRUMENTATION_STATUS_CODE: -?(\d+)')
+    regex_name = re.compile(r'^INSTRUMENTATION_STATUS: test=(.*)')
+    regex_begin_stack = re.compile(r'^INSTRUMENTATION_STATUS: stack=(.*)')
+    regex_end_stack = re.compile(r'^$')
+
+    failed_tests = 0
+    current_test = None
+    current_stack = []
+    mode_stack = False
+    for line in stdout.split("\n"):
+        line = line.rstrip() # strip \r from adb output
+        m = regex_status_code.match(line)
+        if m:
+            c = int(m.group(1))
+            if c == 1:
+                printer.begin(TASK_INSTRUMENTATION_TEST, current_test)
+            elif c == 0:
+                printer.end_pass(TASK_INSTRUMENTATION_TEST, current_test)
+            else:
+                failed_tests += 1
+                current_stack.append("\n")
+                msg = "\n".join(current_stack)
+                printer.end_fail(TASK_INSTRUMENTATION_TEST, current_test, msg.rstrip() + '\n')
+            continue
+
+        m = regex_name.match(line)
+        if m:
+            current_test = m.group(1)
+            continue
+
+        m = regex_begin_stack.match(line)
+        if m:
+            mode_stack = True
+            current_stack = []
+            current_stack.append("  " + m.group(1))
+            continue
+
+        m = regex_end_stack.match(line)
+        if m:
+            mode_stack = False
+            continue
+
+        if mode_stack:
+            current_stack.append("    " + line.strip())
+
+    return failed_tests
+
+def _set_adb_device(option, opt, value, parser):
+    global adb
+    if opt == '-d' or opt == '--device':
+        adb = 'adb -d'
+    if opt == '-e' or opt == '--emulator':
+        adb = 'adb -e'
+    if opt == '-s' or opt == '--serial':
+        adb = 'adb -s ' + value
+
+def _create_opt_parser():
+    parser = optparse.OptionParser()
+    parser.add_option('-d', '--device', action='callback', callback=_set_adb_device,
+            help='pass -d to adb')
+    parser.add_option('-e', '--emulator', action='callback', callback=_set_adb_device,
+            help='pass -e to adb')
+    parser.add_option('-s', '--serial', type="str", action='callback', callback=_set_adb_device,
+            help='pass -s <serical> to adb')
+    parser.add_option('-C', '--no-color', action='store_false',
+            dest='use_color', default=True,
+            help='disable color escape sequences in output')
+    parser.add_option('-q', '--quiet', action='store_true',
+            dest='quiet_mode', default=False,
+            help='quiet mode, output only results')
+    parser.add_option('-b', '--no-build', action='store_false',
+            dest='do_build', default=True,
+            help='do not rebuild test projects')
+    parser.add_option('-k', '--continue', action='store_true',
+            dest='do_continue', default=False,
+            help='do not rebuild test projects')
+    parser.add_option('-i', '--test-idmap', action='store_true',
+            dest='test_idmap', default=False,
+            help='run tests for single overlay')
+    parser.add_option('-0', '--test-no-overlay', action='store_true',
+            dest='test_no_overlay', default=False,
+            help='run tests without any overlay')
+    parser.add_option('-1', '--test-single-overlay', action='store_true',
+            dest='test_single_overlay', default=False,
+            help='run tests for single overlay')
+    parser.add_option('-2', '--test-multiple-overlays', action='store_true',
+            dest='test_multiple_overlays', default=False,
+            help='run tests for multiple overlays')
+    return parser
+
+if __name__ == '__main__':
+    opt_parser = _create_opt_parser()
+    opts, args = opt_parser.parse_args(sys.argv[1:])
+    if not opts.test_idmap and not opts.test_no_overlay and not opts.test_single_overlay and not opts.test_multiple_overlays:
+        opts.test_idmap = True
+        opts.test_no_overlay = True
+        opts.test_single_overlay = True
+        opts.test_multiple_overlays = True
+    if len(args) > 0:
+        opt_parser.error("unexpected arguments: %s" % " ".join(args))
+        # will never reach this: opt_parser.error will call sys.exit
+
+    if opts.quiet_mode:
+        printer = QuietPrinter()
+    else:
+        printer = VerbosePrinter(opts.use_color)
+    tasks = []
+
+    # must be in the same directory as this script for compilation tasks to work
+    script = sys.argv[0]
+    dirname = os.path.dirname(script)
+    wd = os.path.realpath(dirname)
+    os.chdir(wd)
+
+    # build test cases
+    if opts.do_build:
+        tasks.append(CompilationTask('OverlayTest/Android.mk'))
+        tasks.append(CompilationTask('OverlayTestOverlay/Android.mk'))
+        tasks.append(CompilationTask('OverlayAppFirst/Android.mk'))
+        tasks.append(CompilationTask('OverlayAppSecond/Android.mk'))
+
+    # remount filesystem, install test project
+    tasks.append(RootTask())
+    tasks.append(RemountTask())
+    tasks.append(PushTask('/system/app/OverlayTest.apk', '/system/app/OverlayTest.apk'))
+
+    # test idmap
+    if opts.test_idmap:
+        idmaps='/data/local/tmp/idmaps'
+        symlinks='/data/local/tmp/symlinks'
+
+        # idmap --path
+        tasks.append(StopTask())
+        tasks.append(_create_setup_idmap_path_task(idmaps, symlinks))
+        tasks.append(StartTask())
+        tasks.append(IdmapPathTask('/vendor/overlay/framework_a.apk', '/system/framework/framework-res.apk', idmaps + '/a.idmap'))
+        tasks.append(FileExistsTest(idmaps + '/a.idmap'))
+        tasks.append(GrepIdmapTest(idmaps + '/a.idmap', 'bool/config_annoy_dianne', 1))
+
+        # idmap --scan
+        idmap = idmaps + '/vendor@overlay@framework_b.apk@idmap'
+        tasks.append(StopTask())
+        tasks.append(_create_setup_idmap_scan_task(idmaps, symlinks))
+        tasks.append(StartTask())
+        tasks.append(IdmapScanTask('/vendor/overlay', 'android', '/system/framework/framework-res.apk', idmaps, symlinks))
+        tasks.append(FileExistsTest(idmap))
+        tasks.append(GrepIdmapTest(idmap, 'bool/config_annoy_dianne', 1))
+
+        # overlays.list
+        overlays_list_path = '/data/resource-cache/overlays.list'
+        expected_content = '''\
+/vendor/overlay/framework_b.apk /data/resource-cache/vendor@overlay@framework_b.apk@idmap
+'''
+        tasks.append(FileExistsTest(overlays_list_path))
+        tasks.append(Md5Test(overlays_list_path, expected_content))
+
+        # idmap cleanup
+        tasks.append(RmTask(symlinks))
+        tasks.append(RmTask(idmaps))
+
+    # test no overlay
+    if opts.test_no_overlay:
+        tasks.append(StopTask())
+        tasks.append(_create_disable_overlays_task())
+        tasks.append(StartTask())
+        tasks.append(InstrumentationTask('com.android.overlaytest.WithoutOverlayTest'))
+
+    # test single overlay
+    if opts.test_single_overlay:
+        tasks.append(StopTask())
+        tasks.append(_create_enable_single_overlay_task())
+        tasks.append(StartTask())
+        tasks.append(InstrumentationTask('com.android.overlaytest.WithOverlayTest'))
+
+    # test multiple overlays
+    if opts.test_multiple_overlays:
+        tasks.append(StopTask())
+        tasks.append(_create_enable_multiple_overlays_task())
+        tasks.append(StartTask())
+        tasks.append(InstrumentationTask('com.android.overlaytest.WithMultipleOverlaysTest'))
+
+    ignored_errors = 0
+    for t in tasks:
+        type = t.get_type()
+        name = t.get_name()
+        if type == TASK_INSTRUMENTATION:
+            # InstrumentationTask will run several tests, but we want it
+            # to appear as if each test was run individually. Calling
+            # "am instrument" with a single test method is prohibitively
+            # expensive, so let's instead post-process the output to
+            # emulate individual calls.
+            retcode, stdout, stderr = t.execute()
+            if retcode != 0:
+                printer.begin(TASK_INSTRUMENTATION, name)
+                printer.end_fail(TASK_INSTRUMENTATION, name, stderr)
+                sys.exit(retcode)
+            retcode = _handle_instrumentation_task_output(stdout, printer)
+            if retcode != 0:
+                if not opts.do_continue:
+                    sys.exit(retcode)
+                else:
+                    ignored_errors += retcode
+        else:
+            printer.begin(type, name)
+            retcode, stdout, stderr = t.execute()
+            if retcode == 0:
+                printer.end_pass(type, name)
+            if retcode != 0:
+                if len(stderr) == 0:
+                    # hope for output from stdout instead (true for eg adb shell rm)
+                    stderr = stdout
+                printer.end_fail(type, name, stderr)
+                if not opts.do_continue:
+                    sys.exit(retcode)
+                else:
+                    ignored_errors += retcode
+    sys.exit(ignored_errors)
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index bd1edc2..b648d48 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -580,7 +580,7 @@
   <a href="#nm"><code>android:name</code></a> attribute.
 
 <p>The system reads this attribute to determine which activity should be started when
-  the use presses the Up button in the action bar. The system can also use this information to
+  the user presses the Up button in the action bar. The system can also use this information to
   synthesize a back stack of activities with {@link android.app.TaskStackBuilder}.</p>
 
 <p>To support API levels 4 - 16, you can also declare the parent activity with a {@code
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index c62510b..297a2dc 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -56,7 +56,9 @@
 RenderScript kernel language used in this script. Currently, 1 is the only valid value.</li>
 
 <li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
-declares the package name of the Java classes reflected from this script.</li>
+declares the package name of the Java classes reflected from this script.
+Note that your .rs file must be part of your application package, and not in a
+library project.</li>
 
 <li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
 function that you can call from your Java code with arbitrary arguments. These are often useful for
@@ -308,4 +310,4 @@
 <li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
 with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
 object to be garbage collected. This will cause any further use of any object belonging to that
-context to throw an exception.</li> </ol>
\ No newline at end of file
+context to throw an exception.</li> </ol>
diff --git a/docs/html/tools/testing/testing_ui.jd b/docs/html/tools/testing/testing_ui.jd
index 701415e..4318a21 100644
--- a/docs/html/tools/testing/testing_ui.jd
+++ b/docs/html/tools/testing/testing_ui.jd
@@ -90,7 +90,7 @@
          alt="User interface of uiautomatorviewer tool" height="327px" id="figure1"/>
 </a>
 <p class="img-caption">
-    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test deviice.
+    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test device.
 </p>
 
 <p>To analyze the UI components of the application that you want to test:</p>
diff --git a/graphics/java/android/graphics/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java
index 29d14a2..f5b07c1 100644
--- a/graphics/java/android/graphics/pdf/PdfDocument.java
+++ b/graphics/java/android/graphics/pdf/PdfDocument.java
@@ -82,7 +82,7 @@
 
     private final List<PageInfo> mPages = new ArrayList<PageInfo>();
 
-    private int mNativeDocument;
+    private long mNativeDocument;
 
     private Page mCurrentPage;
 
@@ -235,20 +235,20 @@
         }
     }
 
-    private native int nativeCreateDocument();
+    private native long nativeCreateDocument();
 
-    private native void nativeClose(int document);
+    private native void nativeClose(long nativeDocument);
 
-    private native void nativeFinishPage(int document);
+    private native void nativeFinishPage(long nativeDocument);
 
-    private native void nativeWriteTo(int document, OutputStream out, byte[] chunk);
+    private native void nativeWriteTo(long nativeDocument, OutputStream out, byte[] chunk);
 
-    private static native int nativeStartPage(int documentPtr, int pageWidth, int pageHeight,
+    private static native long nativeStartPage(long nativeDocument, int pageWidth, int pageHeight,
             int contentLeft, int contentTop, int contentRight, int contentBottom);
 
     private final class PdfCanvas extends Canvas {
 
-        public PdfCanvas(int nativeCanvas) {
+        public PdfCanvas(long nativeCanvas) {
             super(nativeCanvas);
         }
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
deleted file mode 100644
index afba1a6..0000000
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ /dev/null
@@ -1,1726 +0,0 @@
-/*
- * Copyright (C) 2011-2012 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.
- */
-
-#define LOG_TAG "libRS_jni"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <math.h>
-#include <utils/misc.h>
-
-#include <core/SkBitmap.h>
-#include <core/SkPixelRef.h>
-#include <core/SkStream.h>
-#include <core/SkTemplates.h>
-
-#include <androidfw/Asset.h>
-#include <androidfw/AssetManager.h>
-#include <androidfw/ResourceTypes.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/android_view_Surface.h"
-#include "android_runtime/android_util_AssetManager.h"
-
-#include <rs.h>
-#include <rsEnv.h>
-#include <gui/Surface.h>
-#include <gui/GLConsumer.h>
-#include <gui/Surface.h>
-#include <android_runtime/android_graphics_SurfaceTexture.h>
-
-//#define LOG_API ALOGE
-#define LOG_API(...)
-
-using namespace android;
-
-class AutoJavaStringToUTF8 {
-public:
-    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
-        fCStr = env->GetStringUTFChars(str, NULL);
-        fLength = env->GetStringUTFLength(str);
-    }
-    ~AutoJavaStringToUTF8() {
-        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
-    }
-    const char* c_str() const { return fCStr; }
-    jsize length() const { return fLength; }
-
-private:
-    JNIEnv*     fEnv;
-    jstring     fJStr;
-    const char* fCStr;
-    jsize       fLength;
-};
-
-class AutoJavaStringArrayToUTF8 {
-public:
-    AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength)
-    : mEnv(env), mStrings(strings), mStringsLength(stringsLength) {
-        mCStrings = NULL;
-        mSizeArray = NULL;
-        if (stringsLength > 0) {
-            mCStrings = (const char **)calloc(stringsLength, sizeof(char *));
-            mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t));
-            for (jsize ct = 0; ct < stringsLength; ct ++) {
-                jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
-                mCStrings[ct] = mEnv->GetStringUTFChars(s, NULL);
-                mSizeArray[ct] = mEnv->GetStringUTFLength(s);
-            }
-        }
-    }
-    ~AutoJavaStringArrayToUTF8() {
-        for (jsize ct=0; ct < mStringsLength; ct++) {
-            jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
-            mEnv->ReleaseStringUTFChars(s, mCStrings[ct]);
-        }
-        free(mCStrings);
-        free(mSizeArray);
-    }
-    const char **c_str() const { return mCStrings; }
-    size_t *c_str_len() const { return mSizeArray; }
-    jsize length() const { return mStringsLength; }
-
-private:
-    JNIEnv      *mEnv;
-    jobjectArray mStrings;
-    const char **mCStrings;
-    size_t      *mSizeArray;
-    jsize        mStringsLength;
-};
-
-// ---------------------------------------------------------------------------
-
-static jfieldID gContextId = 0;
-static jfieldID gNativeBitmapID = 0;
-static jfieldID gTypeNativeCache = 0;
-
-static void _nInit(JNIEnv *_env, jclass _this)
-{
-    gContextId             = _env->GetFieldID(_this, "mContext", "I");
-
-    jclass bitmapClass = _env->FindClass("android/graphics/Bitmap");
-    gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "J");
-}
-
-// ---------------------------------------------------------------------------
-
-static void
-nContextFinish(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextFinish, con(%p)", con);
-    rsContextFinish(con);
-}
-
-static void
-nAssignName(JNIEnv *_env, jobject _this, RsContext con, jint obj, jbyteArray str)
-{
-    LOG_API("nAssignName, con(%p), obj(%p)", con, (void *)obj);
-    jint len = _env->GetArrayLength(str);
-    jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
-    rsAssignName(con, (void *)obj, (const char *)cptr, len);
-    _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
-}
-
-static jstring
-nGetName(JNIEnv *_env, jobject _this, RsContext con, jint obj)
-{
-    LOG_API("nGetName, con(%p), obj(%p)", con, (void *)obj);
-    const char *name = NULL;
-    rsaGetName(con, (void *)obj, &name);
-    if(name == NULL || strlen(name) == 0) {
-        return NULL;
-    }
-    return _env->NewStringUTF(name);
-}
-
-static void
-nObjDestroy(JNIEnv *_env, jobject _this, RsContext con, jint obj)
-{
-    LOG_API("nObjDestroy, con(%p) obj(%p)", con, (void *)obj);
-    rsObjDestroy(con, (void *)obj);
-}
-
-// ---------------------------------------------------------------------------
-
-static jint
-nDeviceCreate(JNIEnv *_env, jobject _this)
-{
-    LOG_API("nDeviceCreate");
-    return (jint)rsDeviceCreate();
-}
-
-static void
-nDeviceDestroy(JNIEnv *_env, jobject _this, jint dev)
-{
-    LOG_API("nDeviceDestroy");
-    return rsDeviceDestroy((RsDevice)dev);
-}
-
-static void
-nDeviceSetConfig(JNIEnv *_env, jobject _this, jint dev, jint p, jint value)
-{
-    LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
-    return rsDeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
-}
-
-static jint
-nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver, jint sdkVer, jint ct)
-{
-    LOG_API("nContextCreate");
-    return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
-}
-
-static jint
-nContextCreateGL(JNIEnv *_env, jobject _this, jint dev, jint ver, jint sdkVer,
-                 int colorMin, int colorPref,
-                 int alphaMin, int alphaPref,
-                 int depthMin, int depthPref,
-                 int stencilMin, int stencilPref,
-                 int samplesMin, int samplesPref, float samplesQ,
-                 int dpi)
-{
-    RsSurfaceConfig sc;
-    sc.alphaMin = alphaMin;
-    sc.alphaPref = alphaPref;
-    sc.colorMin = colorMin;
-    sc.colorPref = colorPref;
-    sc.depthMin = depthMin;
-    sc.depthPref = depthPref;
-    sc.samplesMin = samplesMin;
-    sc.samplesPref = samplesPref;
-    sc.samplesQ = samplesQ;
-
-    LOG_API("nContextCreateGL");
-    return (jint)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
-}
-
-static void
-nContextSetPriority(JNIEnv *_env, jobject _this, RsContext con, jint p)
-{
-    LOG_API("ContextSetPriority, con(%p), priority(%i)", con, p);
-    rsContextSetPriority(con, p);
-}
-
-
-
-static void
-nContextSetSurface(JNIEnv *_env, jobject _this, RsContext con, jint width, jint height, jobject wnd)
-{
-    LOG_API("nContextSetSurface, con(%p), width(%i), height(%i), surface(%p)", con, width, height, (Surface *)wnd);
-
-    ANativeWindow * window = NULL;
-    if (wnd == NULL) {
-
-    } else {
-        window = android_view_Surface_getNativeWindow(_env, wnd).get();
-    }
-
-    rsContextSetSurface(con, width, height, window);
-}
-
-static void
-nContextDestroy(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextDestroy, con(%p)", con);
-    rsContextDestroy(con);
-}
-
-static void
-nContextDump(JNIEnv *_env, jobject _this, RsContext con, jint bits)
-{
-    LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
-    rsContextDump((RsContext)con, bits);
-}
-
-static void
-nContextPause(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextPause, con(%p)", con);
-    rsContextPause(con);
-}
-
-static void
-nContextResume(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextResume, con(%p)", con);
-    rsContextResume(con);
-}
-
-
-static jstring
-nContextGetErrorMessage(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextGetErrorMessage, con(%p)", con);
-    char buf[1024];
-
-    size_t receiveLen;
-    uint32_t subID;
-    int id = rsContextGetMessage(con,
-                                 buf, sizeof(buf),
-                                 &receiveLen, sizeof(receiveLen),
-                                 &subID, sizeof(subID));
-    if (!id && receiveLen) {
-        ALOGV("message receive buffer too small.  %i", receiveLen);
-    }
-    return _env->NewStringUTF(buf);
-}
-
-static jint
-nContextGetUserMessage(JNIEnv *_env, jobject _this, RsContext con, jintArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nContextGetMessage, con(%p), len(%i)", con, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    size_t receiveLen;
-    uint32_t subID;
-    int id = rsContextGetMessage(con,
-                                 ptr, len * 4,
-                                 &receiveLen, sizeof(receiveLen),
-                                 &subID, sizeof(subID));
-    if (!id && receiveLen) {
-        ALOGV("message receive buffer too small.  %i", receiveLen);
-    }
-    _env->ReleaseIntArrayElements(data, ptr, 0);
-    return id;
-}
-
-static jint
-nContextPeekMessage(JNIEnv *_env, jobject _this, RsContext con, jintArray auxData)
-{
-    LOG_API("nContextPeekMessage, con(%p)", con);
-    jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
-    size_t receiveLen;
-    uint32_t subID;
-    int id = rsContextPeekMessage(con, &receiveLen, sizeof(receiveLen),
-                                  &subID, sizeof(subID));
-    auxDataPtr[0] = (jint)subID;
-    auxDataPtr[1] = (jint)receiveLen;
-    _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
-    return id;
-}
-
-static void nContextInitToClient(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextInitToClient, con(%p)", con);
-    rsContextInitToClient(con);
-}
-
-static void nContextDeinitToClient(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nContextDeinitToClient, con(%p)", con);
-    rsContextDeinitToClient(con);
-}
-
-static void
-nContextSendMessage(JNIEnv *_env, jobject _this, RsContext con, jint id, jintArray data)
-{
-    jint *ptr = NULL;
-    jint len = 0;
-    if (data) {
-        len = _env->GetArrayLength(data);
-        jint *ptr = _env->GetIntArrayElements(data, NULL);
-    }
-    LOG_API("nContextSendMessage, con(%p), id(%i), len(%i)", con, id, len);
-    rsContextSendMessage(con, id, (const uint8_t *)ptr, len * sizeof(int));
-    if (data) {
-        _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
-    }
-}
-
-
-
-static jint
-nElementCreate(JNIEnv *_env, jobject _this, RsContext con, jint type, jint kind, jboolean norm, jint size)
-{
-    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", con, type, kind, norm, size);
-    return (jint)rsElementCreate(con, (RsDataType)type, (RsDataKind)kind, norm, size);
-}
-
-static jint
-nElementCreate2(JNIEnv *_env, jobject _this, RsContext con,
-                jintArray _ids, jobjectArray _names, jintArray _arraySizes)
-{
-    int fieldCount = _env->GetArrayLength(_ids);
-    LOG_API("nElementCreate2, con(%p)", con);
-
-    jint *ids = _env->GetIntArrayElements(_ids, NULL);
-    jint *arraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
-
-    AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
-
-    const char **nameArray = names.c_str();
-    size_t *sizeArray = names.c_str_len();
-
-    jint id = (jint)rsElementCreate2(con,
-                                     (RsElement *)ids, fieldCount,
-                                     nameArray, fieldCount * sizeof(size_t),  sizeArray,
-                                     (const uint32_t *)arraySizes, fieldCount);
-
-    _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
-    _env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
-    return (jint)id;
-}
-
-static void
-nElementGetNativeData(JNIEnv *_env, jobject _this, RsContext con, jint id, jintArray _elementData)
-{
-    int dataSize = _env->GetArrayLength(_elementData);
-    LOG_API("nElementGetNativeData, con(%p)", con);
-
-    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
-    assert(dataSize == 5);
-
-    uint32_t elementData[5];
-    rsaElementGetNativeData(con, (RsElement)id, elementData, dataSize);
-
-    for(jint i = 0; i < dataSize; i ++) {
-        _env->SetIntArrayRegion(_elementData, i, 1, (const jint*)&elementData[i]);
-    }
-}
-
-
-static void
-nElementGetSubElements(JNIEnv *_env, jobject _this, RsContext con, jint id,
-                       jintArray _IDs,
-                       jobjectArray _names,
-                       jintArray _arraySizes)
-{
-    int dataSize = _env->GetArrayLength(_IDs);
-    LOG_API("nElementGetSubElements, con(%p)", con);
-
-    uint32_t *ids = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
-    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
-    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
-
-    rsaElementGetSubElements(con, (RsElement)id, ids, names, arraySizes, (uint32_t)dataSize);
-
-    for(jint i = 0; i < dataSize; i++) {
-        _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
-        _env->SetIntArrayRegion(_IDs, i, 1, (const jint*)&ids[i]);
-        _env->SetIntArrayRegion(_arraySizes, i, 1, (const jint*)&arraySizes[i]);
-    }
-
-    free(ids);
-    free(names);
-    free(arraySizes);
-}
-
-// -----------------------------------
-
-static int
-nTypeCreate(JNIEnv *_env, jobject _this, RsContext con, RsElement eid,
-            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
-{
-    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
-            con, eid, dimx, dimy, dimz, mips, faces, yuv);
-
-    jint id = (jint)rsTypeCreate(con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
-    return (jint)id;
-}
-
-static void
-nTypeGetNativeData(JNIEnv *_env, jobject _this, RsContext con, jint id, jintArray _typeData)
-{
-    // We are packing 6 items: mDimX; mDimY; mDimZ;
-    // mDimLOD; mDimFaces; mElement; into typeData
-    int elementCount = _env->GetArrayLength(_typeData);
-
-    assert(elementCount == 6);
-    LOG_API("nTypeCreate, con(%p)", con);
-
-    uint32_t typeData[6];
-    rsaTypeGetNativeData(con, (RsType)id, typeData, 6);
-
-    for(jint i = 0; i < elementCount; i ++) {
-        _env->SetIntArrayRegion(_typeData, i, 1, (const jint*)&typeData[i]);
-    }
-}
-
-// -----------------------------------
-
-static jint
-nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mips, jint usage, jint pointer)
-{
-    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", con, (RsElement)type, mips, usage, (void *)pointer);
-    return (jint) rsAllocationCreateTyped(con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
-}
-
-static void
-nAllocationSyncAll(JNIEnv *_env, jobject _this, RsContext con, jint a, jint bits)
-{
-    LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", con, (RsAllocation)a, bits);
-    rsAllocationSyncAll(con, (RsAllocation)a, (RsAllocationUsageType)bits);
-}
-
-static jobject
-nAllocationGetSurface(JNIEnv *_env, jobject _this, RsContext con, jint a)
-{
-    LOG_API("nAllocationGetSurface, con(%p), a(%p)", con, (RsAllocation)a);
-
-    IGraphicBufferProducer *v = (IGraphicBufferProducer *)rsAllocationGetSurface(con, (RsAllocation)a);
-    sp<IGraphicBufferProducer> bp = v;
-    v->decStrong(NULL);
-
-    jobject o = android_view_Surface_createFromIGraphicBufferProducer(_env, bp);
-    return o;
-}
-
-static void
-nAllocationSetSurface(JNIEnv *_env, jobject _this, RsContext con, RsAllocation alloc, jobject sur)
-{
-    LOG_API("nAllocationSetSurface, con(%p), alloc(%p), surface(%p)",
-            con, alloc, (Surface *)sur);
-
-    sp<Surface> s;
-    if (sur != 0) {
-        s = android_view_Surface_getSurface(_env, sur);
-    }
-
-    rsAllocationSetSurface(con, alloc, static_cast<ANativeWindow *>(s.get()));
-}
-
-static void
-nAllocationIoSend(JNIEnv *_env, jobject _this, RsContext con, RsAllocation alloc)
-{
-    LOG_API("nAllocationIoSend, con(%p), alloc(%p)", con, alloc);
-    rsAllocationIoSend(con, alloc);
-}
-
-static void
-nAllocationIoReceive(JNIEnv *_env, jobject _this, RsContext con, RsAllocation alloc)
-{
-    LOG_API("nAllocationIoReceive, con(%p), alloc(%p)", con, alloc);
-    rsAllocationIoReceive(con, alloc);
-}
-
-
-static void
-nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, RsContext con, jint alloc)
-{
-    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", con, (RsAllocation)alloc);
-    rsAllocationGenerateMipmaps(con, (RsAllocation)alloc);
-}
-
-static int
-nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mip, jobject jbitmap, jint usage)
-{
-    SkBitmap const * nativeBitmap =
-            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-
-    bitmap.lockPixels();
-    const void* ptr = bitmap.getPixels();
-    jint id = (jint)rsAllocationCreateFromBitmap(con,
-                                                  (RsType)type, (RsAllocationMipmapControl)mip,
-                                                  ptr, bitmap.getSize(), usage);
-    bitmap.unlockPixels();
-    return id;
-}
-
-static int
-nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mip, jobject jbitmap, jint usage)
-{
-    SkBitmap const * nativeBitmap =
-            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-
-    bitmap.lockPixels();
-    const void* ptr = bitmap.getPixels();
-    jint id = (jint)rsAllocationCreateTyped(con,
-                                            (RsType)type, (RsAllocationMipmapControl)mip,
-                                            (uint32_t)usage, (size_t)ptr);
-    bitmap.unlockPixels();
-    return id;
-}
-
-static int
-nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mip, jobject jbitmap, jint usage)
-{
-    SkBitmap const * nativeBitmap =
-            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-
-    bitmap.lockPixels();
-    const void* ptr = bitmap.getPixels();
-    jint id = (jint)rsAllocationCubeCreateFromBitmap(con,
-                                                      (RsType)type, (RsAllocationMipmapControl)mip,
-                                                      ptr, bitmap.getSize(), usage);
-    bitmap.unlockPixels();
-    return id;
-}
-
-static void
-nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject jbitmap)
-{
-    SkBitmap const * nativeBitmap =
-            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-    int w = bitmap.width();
-    int h = bitmap.height();
-
-    bitmap.lockPixels();
-    const void* ptr = bitmap.getPixels();
-    rsAllocation2DData(con, (RsAllocation)alloc, 0, 0,
-                       0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
-                       w, h, ptr, bitmap.getSize(), 0);
-    bitmap.unlockPixels();
-}
-
-static void
-nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject jbitmap)
-{
-    SkBitmap const * nativeBitmap =
-            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
-    const SkBitmap& bitmap(*nativeBitmap);
-
-    bitmap.lockPixels();
-    void* ptr = bitmap.getPixels();
-    rsAllocationCopyToBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize());
-    bitmap.unlockPixels();
-    bitmap.notifyPixelsChanged();
-}
-
-static void ReleaseBitmapCallback(void *bmp)
-{
-    SkBitmap const * nativeBitmap = (SkBitmap const *)bmp;
-    nativeBitmap->unlockPixels();
-}
-
-
-static void
-nAllocationData1D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jintArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
-    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jshortArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DData_s, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
-    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jbyteArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DData_b, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jfloatArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-//    native void rsnAllocationElementData1D(int con, int id, int xoff, int compIdx, byte[] d, int sizeBytes);
-nAllocationElementData1D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint compIdx, jbyteArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation1DElementData(con, (RsAllocation)alloc, offset, lod, ptr, sizeBytes, compIdx);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
-                    jint w, jint h, jshortArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DData_s, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
-                    jint w, jint h, jbyteArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DData_b, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
-                    jint w, jint h, jintArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
-                    jint w, jint h, jfloatArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_alloc(JNIEnv *_env, jobject _this, RsContext con,
-                        jint dstAlloc, jint dstXoff, jint dstYoff,
-                        jint dstMip, jint dstFace,
-                        jint width, jint height,
-                        jint srcAlloc, jint srcXoff, jint srcYoff,
-                        jint srcMip, jint srcFace)
-{
-    LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
-            " dstMip(%i), dstFace(%i), width(%i), height(%i),"
-            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
-            con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
-            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
-
-    rsAllocationCopy2DRange(con,
-                            (RsAllocation)dstAlloc,
-                            dstXoff, dstYoff,
-                            dstMip, dstFace,
-                            width, height,
-                            (RsAllocation)srcAlloc,
-                            srcXoff, srcYoff,
-                            srcMip, srcFace);
-}
-
-static void
-nAllocationData3D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint zoff, jint lod,
-                    jint w, jint h, jint d, jshortArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation3DData_s, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    rsAllocation3DData(con, (RsAllocation)alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData3D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint zoff, jint lod,
-                    jint w, jint h, jint d, jbyteArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation3DData_b, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation3DData(con, (RsAllocation)alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData3D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint zoff, jint lod,
-                    jint w, jint h, jint d, jintArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation3DData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocation3DData(con, (RsAllocation)alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData3D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint zoff, jint lod,
-                    jint w, jint h, jint d, jfloatArray data, int sizeBytes)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation3DData_f, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocation3DData(con, (RsAllocation)alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData3D_alloc(JNIEnv *_env, jobject _this, RsContext con,
-                        jint dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
-                        jint dstMip,
-                        jint width, jint height, jint depth,
-                        jint srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff,
-                        jint srcMip)
-{
-    LOG_API("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
-            " dstMip(%i), width(%i), height(%i),"
-            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)",
-            con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
-            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
-
-    rsAllocationCopy3DRange(con,
-                            (RsAllocation)dstAlloc,
-                            dstXoff, dstYoff, dstZoff, dstMip,
-                            width, height, depth,
-                            (RsAllocation)srcAlloc,
-                            srcXoff, srcYoff, srcZoff, srcMip);
-}
-
-static void
-nAllocationRead_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jintArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(int));
-    _env->ReleaseIntArrayElements(data, ptr, 0);
-}
-
-static void
-nAllocationRead_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jshortArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(short));
-    _env->ReleaseShortArrayElements(data, ptr, 0);
-}
-
-static void
-nAllocationRead_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jbyteArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(char));
-    _env->ReleaseByteArrayElements(data, ptr, 0);
-}
-
-static void
-nAllocationRead_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jfloatArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    rsAllocationRead(con, (RsAllocation)alloc, ptr, length * sizeof(float));
-    _env->ReleaseFloatArrayElements(data, ptr, 0);
-}
-
-static jint
-nAllocationGetType(JNIEnv *_env, jobject _this, RsContext con, jint a)
-{
-    LOG_API("nAllocationGetType, con(%p), a(%p)", con, (RsAllocation)a);
-    return (jint) rsaAllocationGetType(con, (RsAllocation)a);
-}
-
-static void
-nAllocationResize1D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint dimX)
-{
-    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", con, (RsAllocation)alloc, dimX);
-    rsAllocationResize1D(con, (RsAllocation)alloc, dimX);
-}
-
-// -----------------------------------
-
-static int
-nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con, jint native_asset)
-{
-    ALOGV("______nFileA3D %u", (uint32_t) native_asset);
-
-    Asset* asset = reinterpret_cast<Asset*>(native_asset);
-
-    jint id = (jint)rsaFileA3DCreateFromMemory(con, asset->getBuffer(false), asset->getLength());
-    return id;
-}
-
-static int
-nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, RsContext con, jobject _assetMgr, jstring _path)
-{
-    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
-    if (mgr == NULL) {
-        return 0;
-    }
-
-    AutoJavaStringToUTF8 str(_env, _path);
-    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
-    if (asset == NULL) {
-        return 0;
-    }
-
-    jint id = (jint)rsaFileA3DCreateFromAsset(con, asset);
-    return id;
-}
-
-static int
-nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, RsContext con, jstring fileName)
-{
-    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
-    jint id = (jint)rsaFileA3DCreateFromFile(con, fileNameUTF.c_str());
-
-    return id;
-}
-
-static int
-nFileA3DGetNumIndexEntries(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D)
-{
-    int32_t numEntries = 0;
-    rsaFileA3DGetNumIndexEntries(con, &numEntries, (RsFile)fileA3D);
-    return numEntries;
-}
-
-static void
-nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries)
-{
-    ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
-    RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
-
-    rsaFileA3DGetIndexEntries(con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
-
-    for(jint i = 0; i < numEntries; i ++) {
-        _env->SetObjectArrayElement(_entries, i, _env->NewStringUTF(fileEntries[i].objectName));
-        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&fileEntries[i].classID);
-    }
-
-    free(fileEntries);
-}
-
-static int
-nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, RsContext con, jint fileA3D, jint index)
-{
-    ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
-    jint id = (jint)rsaFileA3DGetEntryByIndex(con, (uint32_t)index, (RsFile)fileA3D);
-    return id;
-}
-
-// -----------------------------------
-
-static int
-nFontCreateFromFile(JNIEnv *_env, jobject _this, RsContext con,
-                    jstring fileName, jfloat fontSize, jint dpi)
-{
-    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
-    jint id = (jint)rsFontCreateFromFile(con,
-                                         fileNameUTF.c_str(), fileNameUTF.length(),
-                                         fontSize, dpi);
-
-    return id;
-}
-
-static int
-nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con,
-                           jstring name, jfloat fontSize, jint dpi, jint native_asset)
-{
-    Asset* asset = reinterpret_cast<Asset*>(native_asset);
-    AutoJavaStringToUTF8 nameUTF(_env, name);
-
-    jint id = (jint)rsFontCreateFromMemory(con,
-                                           nameUTF.c_str(), nameUTF.length(),
-                                           fontSize, dpi,
-                                           asset->getBuffer(false), asset->getLength());
-    return id;
-}
-
-static int
-nFontCreateFromAsset(JNIEnv *_env, jobject _this, RsContext con, jobject _assetMgr, jstring _path,
-                     jfloat fontSize, jint dpi)
-{
-    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
-    if (mgr == NULL) {
-        return 0;
-    }
-
-    AutoJavaStringToUTF8 str(_env, _path);
-    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
-    if (asset == NULL) {
-        return 0;
-    }
-
-    jint id = (jint)rsFontCreateFromMemory(con,
-                                           str.c_str(), str.length(),
-                                           fontSize, dpi,
-                                           asset->getBuffer(false), asset->getLength());
-    delete asset;
-    return id;
-}
-
-// -----------------------------------
-
-static void
-nScriptBindAllocation(JNIEnv *_env, jobject _this, RsContext con, jint script, jint alloc, jint slot)
-{
-    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", con, (RsScript)script, (RsAllocation)alloc, slot);
-    rsScriptBindAllocation(con, (RsScript)script, (RsAllocation)alloc, slot);
-}
-
-static void
-nScriptSetVarI(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jint val)
-{
-    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", con, (void *)script, slot, val);
-    rsScriptSetVarI(con, (RsScript)script, slot, val);
-}
-
-static jint
-nScriptGetVarI(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot)
-{
-    LOG_API("nScriptGetVarI, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    int value = 0;
-    rsScriptGetVarV(con, (RsScript)script, slot, &value, sizeof(value));
-    return value;
-}
-
-static void
-nScriptSetVarObj(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jint val)
-{
-    LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", con, (void *)script, slot, val);
-    rsScriptSetVarObj(con, (RsScript)script, slot, (RsObjectBase)val);
-}
-
-static void
-nScriptSetVarJ(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jlong val)
-{
-    LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", con, (void *)script, slot, val);
-    rsScriptSetVarJ(con, (RsScript)script, slot, val);
-}
-
-static jlong
-nScriptGetVarJ(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot)
-{
-    LOG_API("nScriptGetVarJ, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jlong value = 0;
-    rsScriptGetVarV(con, (RsScript)script, slot, &value, sizeof(value));
-    return value;
-}
-
-static void
-nScriptSetVarF(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, float val)
-{
-    LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", con, (void *)script, slot, val);
-    rsScriptSetVarF(con, (RsScript)script, slot, val);
-}
-
-static jfloat
-nScriptGetVarF(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot)
-{
-    LOG_API("nScriptGetVarF, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jfloat value = 0;
-    rsScriptGetVarV(con, (RsScript)script, slot, &value, sizeof(value));
-    return value;
-}
-
-static void
-nScriptSetVarD(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, double val)
-{
-    LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", con, (void *)script, slot, val);
-    rsScriptSetVarD(con, (RsScript)script, slot, val);
-}
-
-static jdouble
-nScriptGetVarD(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot)
-{
-    LOG_API("nScriptGetVarD, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jdouble value = 0;
-    rsScriptGetVarV(con, (RsScript)script, slot, &value, sizeof(value));
-    return value;
-}
-
-static void
-nScriptSetVarV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data)
-{
-    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jint len = _env->GetArrayLength(data);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsScriptSetVarV(con, (RsScript)script, slot, ptr, len);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nScriptGetVarV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data)
-{
-    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jint len = _env->GetArrayLength(data);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsScriptGetVarV(con, (RsScript)script, slot, ptr, len);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nScriptSetVarVE(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data, jint elem, jintArray dims)
-{
-    LOG_API("nScriptSetVarVE, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jint len = _env->GetArrayLength(data);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
-    jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
-    rsScriptSetVarVE(con, (RsScript)script, slot, ptr, len, (RsElement)elem,
-                     (const size_t*) dimsPtr, dimsLen);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-    _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
-}
-
-
-static void
-nScriptSetTimeZone(JNIEnv *_env, jobject _this, RsContext con, jint script, jbyteArray timeZone)
-{
-    LOG_API("nScriptCSetTimeZone, con(%p), s(%p), timeZone(%s)", con, (void *)script, (const char *)timeZone);
-
-    jint length = _env->GetArrayLength(timeZone);
-    jbyte* timeZone_ptr;
-    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
-
-    rsScriptSetTimeZone(con, (RsScript)script, (const char *)timeZone_ptr, length);
-
-    if (timeZone_ptr) {
-        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
-    }
-}
-
-static void
-nScriptInvoke(JNIEnv *_env, jobject _this, RsContext con, jint obj, jint slot)
-{
-    LOG_API("nScriptInvoke, con(%p), script(%p)", con, (void *)obj);
-    rsScriptInvoke(con, (RsScript)obj, slot);
-}
-
-static void
-nScriptInvokeV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data)
-{
-    LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jint len = _env->GetArrayLength(data);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsScriptInvokeV(con, (RsScript)script, slot, ptr, len);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nScriptForEach(JNIEnv *_env, jobject _this, RsContext con,
-               jint script, jint slot, jint ain, jint aout)
-{
-    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    rsScriptForEach(con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, NULL, 0, NULL, 0);
-}
-static void
-nScriptForEachV(JNIEnv *_env, jobject _this, RsContext con,
-                jint script, jint slot, jint ain, jint aout, jbyteArray params)
-{
-    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jint len = _env->GetArrayLength(params);
-    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
-    rsScriptForEach(con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, ptr, len, NULL, 0);
-    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
-}
-
-static void
-nScriptForEachClipped(JNIEnv *_env, jobject _this, RsContext con,
-                      jint script, jint slot, jint ain, jint aout,
-                      jint xstart, jint xend,
-                      jint ystart, jint yend, jint zstart, jint zend)
-{
-    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    RsScriptCall sc;
-    sc.xStart = xstart;
-    sc.xEnd = xend;
-    sc.yStart = ystart;
-    sc.yEnd = yend;
-    sc.zStart = zstart;
-    sc.zEnd = zend;
-    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
-    sc.arrayStart = 0;
-    sc.arrayEnd = 0;
-    rsScriptForEach(con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, NULL, 0, &sc, sizeof(sc));
-}
-
-static void
-nScriptForEachClippedV(JNIEnv *_env, jobject _this, RsContext con,
-                       jint script, jint slot, jint ain, jint aout,
-                       jbyteArray params, jint xstart, jint xend,
-                       jint ystart, jint yend, jint zstart, jint zend)
-{
-    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
-    jint len = _env->GetArrayLength(params);
-    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
-    RsScriptCall sc;
-    sc.xStart = xstart;
-    sc.xEnd = xend;
-    sc.yStart = ystart;
-    sc.yEnd = yend;
-    sc.zStart = zstart;
-    sc.zEnd = zend;
-    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
-    sc.arrayStart = 0;
-    sc.arrayEnd = 0;
-    rsScriptForEach(con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, ptr, len, &sc, sizeof(sc));
-    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
-}
-
-// -----------------------------------
-
-static jint
-nScriptCCreate(JNIEnv *_env, jobject _this, RsContext con,
-               jstring resName, jstring cacheDir,
-               jbyteArray scriptRef, jint length)
-{
-    LOG_API("nScriptCCreate, con(%p)", con);
-
-    AutoJavaStringToUTF8 resNameUTF(_env, resName);
-    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
-    jint ret = 0;
-    jbyte* script_ptr = NULL;
-    jint _exception = 0;
-    jint remaining;
-    if (!scriptRef) {
-        _exception = 1;
-        //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
-        goto exit;
-    }
-    if (length < 0) {
-        _exception = 1;
-        //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
-        goto exit;
-    }
-    remaining = _env->GetArrayLength(scriptRef);
-    if (remaining < length) {
-        _exception = 1;
-        //jniThrowException(_env, "java/lang/IllegalArgumentException",
-        //        "length > script.length - offset");
-        goto exit;
-    }
-    script_ptr = (jbyte *)
-        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
-
-    //rsScriptCSetText(con, (const char *)script_ptr, length);
-
-    ret = (jint)rsScriptCCreate(con,
-                                resNameUTF.c_str(), resNameUTF.length(),
-                                cacheDirUTF.c_str(), cacheDirUTF.length(),
-                                (const char *)script_ptr, length);
-
-exit:
-    if (script_ptr) {
-        _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
-                _exception ? JNI_ABORT: 0);
-    }
-
-    return ret;
-}
-
-static jint
-nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, RsContext con, jint id, jint eid)
-{
-    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", con, id, (void *)eid);
-    return (jint)rsScriptIntrinsicCreate(con, id, (RsElement)eid);
-}
-
-static jint
-nScriptKernelIDCreate(JNIEnv *_env, jobject _this, RsContext con, jint sid, jint slot, jint sig)
-{
-    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con, (void *)sid, slot, sig);
-    return (jint)rsScriptKernelIDCreate(con, (RsScript)sid, slot, sig);
-}
-
-static jint
-nScriptFieldIDCreate(JNIEnv *_env, jobject _this, RsContext con, jint sid, jint slot)
-{
-    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", con, (void *)sid, slot);
-    return (jint)rsScriptFieldIDCreate(con, (RsScript)sid, slot);
-}
-
-static jint
-nScriptGroupCreate(JNIEnv *_env, jobject _this, RsContext con, jintArray _kernels, jintArray _src,
-    jintArray _dstk, jintArray _dstf, jintArray _types)
-{
-    LOG_API("nScriptGroupCreate, con(%p)", con);
-
-    jint kernelsLen = _env->GetArrayLength(_kernels) * sizeof(int);
-    jint *kernelsPtr = _env->GetIntArrayElements(_kernels, NULL);
-    jint srcLen = _env->GetArrayLength(_src) * sizeof(int);
-    jint *srcPtr = _env->GetIntArrayElements(_src, NULL);
-    jint dstkLen = _env->GetArrayLength(_dstk) * sizeof(int);
-    jint *dstkPtr = _env->GetIntArrayElements(_dstk, NULL);
-    jint dstfLen = _env->GetArrayLength(_dstf) * sizeof(int);
-    jint *dstfPtr = _env->GetIntArrayElements(_dstf, NULL);
-    jint typesLen = _env->GetArrayLength(_types) * sizeof(int);
-    jint *typesPtr = _env->GetIntArrayElements(_types, NULL);
-
-    int id = (int)rsScriptGroupCreate(con,
-                               (RsScriptKernelID *)kernelsPtr, kernelsLen,
-                               (RsScriptKernelID *)srcPtr, srcLen,
-                               (RsScriptKernelID *)dstkPtr, dstkLen,
-                               (RsScriptFieldID *)dstfPtr, dstfLen,
-                               (RsType *)typesPtr, typesLen);
-
-    _env->ReleaseIntArrayElements(_kernels, kernelsPtr, 0);
-    _env->ReleaseIntArrayElements(_src, srcPtr, 0);
-    _env->ReleaseIntArrayElements(_dstk, dstkPtr, 0);
-    _env->ReleaseIntArrayElements(_dstf, dstfPtr, 0);
-    _env->ReleaseIntArrayElements(_types, typesPtr, 0);
-    return id;
-}
-
-static void
-nScriptGroupSetInput(JNIEnv *_env, jobject _this, RsContext con, jint gid, jint kid, jint alloc)
-{
-    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", con,
-        (void *)gid, (void *)kid, (void *)alloc);
-    rsScriptGroupSetInput(con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
-}
-
-static void
-nScriptGroupSetOutput(JNIEnv *_env, jobject _this, RsContext con, jint gid, jint kid, jint alloc)
-{
-    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", con,
-        (void *)gid, (void *)kid, (void *)alloc);
-    rsScriptGroupSetOutput(con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
-}
-
-static void
-nScriptGroupExecute(JNIEnv *_env, jobject _this, RsContext con, jint gid)
-{
-    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", con, (void *)gid);
-    rsScriptGroupExecute(con, (RsScriptGroup)gid);
-}
-
-// ---------------------------------------------------------------------------
-
-static jint
-nProgramStoreCreate(JNIEnv *_env, jobject _this, RsContext con,
-                    jboolean colorMaskR, jboolean colorMaskG, jboolean colorMaskB, jboolean colorMaskA,
-                    jboolean depthMask, jboolean ditherEnable,
-                    jint srcFunc, jint destFunc,
-                    jint depthFunc)
-{
-    LOG_API("nProgramStoreCreate, con(%p)", con);
-    return (jint)rsProgramStoreCreate(con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
-                                      depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
-                                      (RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
-}
-
-// ---------------------------------------------------------------------------
-
-static void
-nProgramBindConstants(JNIEnv *_env, jobject _this, RsContext con, jint vpv, jint slot, jint a)
-{
-    LOG_API("nProgramBindConstants, con(%p), vpf(%p), sloat(%i), a(%p)", con, (RsProgramVertex)vpv, slot, (RsAllocation)a);
-    rsProgramBindConstants(con, (RsProgram)vpv, slot, (RsAllocation)a);
-}
-
-static void
-nProgramBindTexture(JNIEnv *_env, jobject _this, RsContext con, jint vpf, jint slot, jint a)
-{
-    LOG_API("nProgramBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
-    rsProgramBindTexture(con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
-}
-
-static void
-nProgramBindSampler(JNIEnv *_env, jobject _this, RsContext con, jint vpf, jint slot, jint a)
-{
-    LOG_API("nProgramBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
-    rsProgramBindSampler(con, (RsProgramFragment)vpf, slot, (RsSampler)a);
-}
-
-// ---------------------------------------------------------------------------
-
-static jint
-nProgramFragmentCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader,
-                       jobjectArray texNames, jintArray params)
-{
-    AutoJavaStringToUTF8 shaderUTF(_env, shader);
-    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
-    jint paramLen = _env->GetArrayLength(params);
-
-    int texCount = _env->GetArrayLength(texNames);
-    AutoJavaStringArrayToUTF8 names(_env, texNames, texCount);
-    const char ** nameArray = names.c_str();
-    size_t* sizeArray = names.c_str_len();
-
-    LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", con, paramLen);
-
-    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF.c_str(), shaderUTF.length(),
-                                             nameArray, texCount, sizeArray,
-                                             (uint32_t *)paramPtr, paramLen);
-
-    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
-    return ret;
-}
-
-
-// ---------------------------------------------------------------------------
-
-static jint
-nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader,
-                     jobjectArray texNames, jintArray params)
-{
-    AutoJavaStringToUTF8 shaderUTF(_env, shader);
-    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
-    jint paramLen = _env->GetArrayLength(params);
-
-    LOG_API("nProgramVertexCreate, con(%p), paramLen(%i)", con, paramLen);
-
-    int texCount = _env->GetArrayLength(texNames);
-    AutoJavaStringArrayToUTF8 names(_env, texNames, texCount);
-    const char ** nameArray = names.c_str();
-    size_t* sizeArray = names.c_str_len();
-
-    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF.c_str(), shaderUTF.length(),
-                                           nameArray, texCount, sizeArray,
-                                           (uint32_t *)paramPtr, paramLen);
-
-    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
-    return ret;
-}
-
-// ---------------------------------------------------------------------------
-
-static jint
-nProgramRasterCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean pointSprite, jint cull)
-{
-    LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", con, pointSprite, cull);
-    return (jint)rsProgramRasterCreate(con, pointSprite, (RsCullMode)cull);
-}
-
-
-// ---------------------------------------------------------------------------
-
-static void
-nContextBindRootScript(JNIEnv *_env, jobject _this, RsContext con, jint script)
-{
-    LOG_API("nContextBindRootScript, con(%p), script(%p)", con, (RsScript)script);
-    rsContextBindRootScript(con, (RsScript)script);
-}
-
-static void
-nContextBindProgramStore(JNIEnv *_env, jobject _this, RsContext con, jint pfs)
-{
-    LOG_API("nContextBindProgramStore, con(%p), pfs(%p)", con, (RsProgramStore)pfs);
-    rsContextBindProgramStore(con, (RsProgramStore)pfs);
-}
-
-static void
-nContextBindProgramFragment(JNIEnv *_env, jobject _this, RsContext con, jint pf)
-{
-    LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", con, (RsProgramFragment)pf);
-    rsContextBindProgramFragment(con, (RsProgramFragment)pf);
-}
-
-static void
-nContextBindProgramVertex(JNIEnv *_env, jobject _this, RsContext con, jint pf)
-{
-    LOG_API("nContextBindProgramVertex, con(%p), pf(%p)", con, (RsProgramVertex)pf);
-    rsContextBindProgramVertex(con, (RsProgramVertex)pf);
-}
-
-static void
-nContextBindProgramRaster(JNIEnv *_env, jobject _this, RsContext con, jint pf)
-{
-    LOG_API("nContextBindProgramRaster, con(%p), pf(%p)", con, (RsProgramRaster)pf);
-    rsContextBindProgramRaster(con, (RsProgramRaster)pf);
-}
-
-
-// ---------------------------------------------------------------------------
-
-static jint
-nSamplerCreate(JNIEnv *_env, jobject _this, RsContext con, jint magFilter, jint minFilter,
-               jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
-{
-    LOG_API("nSamplerCreate, con(%p)", con);
-    return (jint)rsSamplerCreate(con,
-                                 (RsSamplerValue)magFilter,
-                                 (RsSamplerValue)minFilter,
-                                 (RsSamplerValue)wrapS,
-                                 (RsSamplerValue)wrapT,
-                                 (RsSamplerValue)wrapR,
-                                 aniso);
-}
-
-// ---------------------------------------------------------------------------
-
-//native int  rsnPathCreate(int con, int prim, boolean isStatic, int vtx, int loop, float q);
-static jint
-nPathCreate(JNIEnv *_env, jobject _this, RsContext con, jint prim, jboolean isStatic, jint _vtx, jint _loop, jfloat q) {
-    LOG_API("nPathCreate, con(%p)", con);
-
-    int id = (int)rsPathCreate(con, (RsPathPrimitive)prim, isStatic,
-                               (RsAllocation)_vtx,
-                               (RsAllocation)_loop, q);
-    return id;
-}
-
-static jint
-nMeshCreate(JNIEnv *_env, jobject _this, RsContext con, jintArray _vtx, jintArray _idx, jintArray _prim)
-{
-    LOG_API("nMeshCreate, con(%p)", con);
-
-    jint vtxLen = _env->GetArrayLength(_vtx);
-    jint *vtxPtr = _env->GetIntArrayElements(_vtx, NULL);
-    jint idxLen = _env->GetArrayLength(_idx);
-    jint *idxPtr = _env->GetIntArrayElements(_idx, NULL);
-    jint primLen = _env->GetArrayLength(_prim);
-    jint *primPtr = _env->GetIntArrayElements(_prim, NULL);
-
-    int id = (int)rsMeshCreate(con,
-                               (RsAllocation *)vtxPtr, vtxLen,
-                               (RsAllocation *)idxPtr, idxLen,
-                               (uint32_t *)primPtr, primLen);
-
-    _env->ReleaseIntArrayElements(_vtx, vtxPtr, 0);
-    _env->ReleaseIntArrayElements(_idx, idxPtr, 0);
-    _env->ReleaseIntArrayElements(_prim, primPtr, 0);
-    return id;
-}
-
-static jint
-nMeshGetVertexBufferCount(JNIEnv *_env, jobject _this, RsContext con, jint mesh)
-{
-    LOG_API("nMeshGetVertexBufferCount, con(%p), Mesh(%p)", con, (RsMesh)mesh);
-    jint vtxCount = 0;
-    rsaMeshGetVertexBufferCount(con, (RsMesh)mesh, &vtxCount);
-    return vtxCount;
-}
-
-static jint
-nMeshGetIndexCount(JNIEnv *_env, jobject _this, RsContext con, jint mesh)
-{
-    LOG_API("nMeshGetIndexCount, con(%p), Mesh(%p)", con, (RsMesh)mesh);
-    jint idxCount = 0;
-    rsaMeshGetIndexCount(con, (RsMesh)mesh, &idxCount);
-    return idxCount;
-}
-
-static void
-nMeshGetVertices(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jintArray _ids, int numVtxIDs)
-{
-    LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", con, (RsMesh)mesh);
-
-    RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numVtxIDs * sizeof(RsAllocation));
-    rsaMeshGetVertices(con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
-
-    for(jint i = 0; i < numVtxIDs; i ++) {
-        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&allocs[i]);
-    }
-
-    free(allocs);
-}
-
-static void
-nMeshGetIndices(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jintArray _idxIds, jintArray _primitives, int numIndices)
-{
-    LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", con, (RsMesh)mesh);
-
-    RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numIndices * sizeof(RsAllocation));
-    uint32_t *prims= (uint32_t*)malloc((uint32_t)numIndices * sizeof(uint32_t));
-
-    rsaMeshGetIndices(con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
-
-    for(jint i = 0; i < numIndices; i ++) {
-        _env->SetIntArrayRegion(_idxIds, i, 1, (const jint*)&allocs[i]);
-        _env->SetIntArrayRegion(_primitives, i, 1, (const jint*)&prims[i]);
-    }
-
-    free(allocs);
-    free(prims);
-}
-
-// ---------------------------------------------------------------------------
-
-
-static const char *classPathName = "android/renderscript/RenderScript";
-
-static JNINativeMethod methods[] = {
-{"_nInit",                         "()V",                                     (void*)_nInit },
-
-{"nDeviceCreate",                  "()I",                                     (void*)nDeviceCreate },
-{"nDeviceDestroy",                 "(I)V",                                    (void*)nDeviceDestroy },
-{"nDeviceSetConfig",               "(III)V",                                  (void*)nDeviceSetConfig },
-{"nContextGetUserMessage",         "(I[I)I",                                  (void*)nContextGetUserMessage },
-{"nContextGetErrorMessage",        "(I)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
-{"nContextPeekMessage",            "(I[I)I",                                  (void*)nContextPeekMessage },
-
-{"nContextInitToClient",           "(I)V",                                    (void*)nContextInitToClient },
-{"nContextDeinitToClient",         "(I)V",                                    (void*)nContextDeinitToClient },
-
-
-// All methods below are thread protected in java.
-{"rsnContextCreate",                 "(IIII)I",                               (void*)nContextCreate },
-{"rsnContextCreateGL",               "(IIIIIIIIIIIIIFI)I",                    (void*)nContextCreateGL },
-{"rsnContextFinish",                 "(I)V",                                  (void*)nContextFinish },
-{"rsnContextSetPriority",            "(II)V",                                 (void*)nContextSetPriority },
-{"rsnContextSetSurface",             "(IIILandroid/view/Surface;)V",          (void*)nContextSetSurface },
-{"rsnContextDestroy",                "(I)V",                                  (void*)nContextDestroy },
-{"rsnContextDump",                   "(II)V",                                 (void*)nContextDump },
-{"rsnContextPause",                  "(I)V",                                  (void*)nContextPause },
-{"rsnContextResume",                 "(I)V",                                  (void*)nContextResume },
-{"rsnContextSendMessage",            "(II[I)V",                               (void*)nContextSendMessage },
-{"rsnAssignName",                    "(II[B)V",                               (void*)nAssignName },
-{"rsnGetName",                       "(II)Ljava/lang/String;",                (void*)nGetName },
-{"rsnObjDestroy",                    "(II)V",                                 (void*)nObjDestroy },
-
-{"rsnFileA3DCreateFromFile",         "(ILjava/lang/String;)I",                (void*)nFileA3DCreateFromFile },
-{"rsnFileA3DCreateFromAssetStream",  "(II)I",                                 (void*)nFileA3DCreateFromAssetStream },
-{"rsnFileA3DCreateFromAsset",        "(ILandroid/content/res/AssetManager;Ljava/lang/String;)I",            (void*)nFileA3DCreateFromAsset },
-{"rsnFileA3DGetNumIndexEntries",     "(II)I",                                 (void*)nFileA3DGetNumIndexEntries },
-{"rsnFileA3DGetIndexEntries",        "(III[I[Ljava/lang/String;)V",           (void*)nFileA3DGetIndexEntries },
-{"rsnFileA3DGetEntryByIndex",        "(III)I",                                (void*)nFileA3DGetEntryByIndex },
-
-{"rsnFontCreateFromFile",            "(ILjava/lang/String;FI)I",              (void*)nFontCreateFromFile },
-{"rsnFontCreateFromAssetStream",     "(ILjava/lang/String;FII)I",             (void*)nFontCreateFromAssetStream },
-{"rsnFontCreateFromAsset",        "(ILandroid/content/res/AssetManager;Ljava/lang/String;FI)I",            (void*)nFontCreateFromAsset },
-
-{"rsnElementCreate",                 "(IIIZI)I",                              (void*)nElementCreate },
-{"rsnElementCreate2",                "(I[I[Ljava/lang/String;[I)I",           (void*)nElementCreate2 },
-{"rsnElementGetNativeData",          "(II[I)V",                               (void*)nElementGetNativeData },
-{"rsnElementGetSubElements",         "(II[I[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
-
-{"rsnTypeCreate",                    "(IIIIIZZI)I",                           (void*)nTypeCreate },
-{"rsnTypeGetNativeData",             "(II[I)V",                               (void*)nTypeGetNativeData },
-
-{"rsnAllocationCreateTyped",         "(IIIII)I",                               (void*)nAllocationCreateTyped },
-{"rsnAllocationCreateFromBitmap",    "(IIILandroid/graphics/Bitmap;I)I",      (void*)nAllocationCreateFromBitmap },
-{"rsnAllocationCreateBitmapBackedAllocation",    "(IIILandroid/graphics/Bitmap;I)I",      (void*)nAllocationCreateBitmapBackedAllocation },
-{"rsnAllocationCubeCreateFromBitmap","(IIILandroid/graphics/Bitmap;I)I",      (void*)nAllocationCubeCreateFromBitmap },
-
-{"rsnAllocationCopyFromBitmap",      "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
-{"rsnAllocationCopyToBitmap",        "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
-
-{"rsnAllocationSyncAll",             "(III)V",                                (void*)nAllocationSyncAll },
-{"rsnAllocationGetSurface",          "(II)Landroid/view/Surface;",            (void*)nAllocationGetSurface },
-{"rsnAllocationSetSurface",          "(IILandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
-{"rsnAllocationIoSend",              "(II)V",                                 (void*)nAllocationIoSend },
-{"rsnAllocationIoReceive",           "(II)V",                                 (void*)nAllocationIoReceive },
-{"rsnAllocationData1D",              "(IIIII[II)V",                           (void*)nAllocationData1D_i },
-{"rsnAllocationData1D",              "(IIIII[SI)V",                           (void*)nAllocationData1D_s },
-{"rsnAllocationData1D",              "(IIIII[BI)V",                           (void*)nAllocationData1D_b },
-{"rsnAllocationData1D",              "(IIIII[FI)V",                           (void*)nAllocationData1D_f },
-{"rsnAllocationElementData1D",       "(IIIII[BI)V",                           (void*)nAllocationElementData1D },
-{"rsnAllocationData2D",              "(IIIIIIII[II)V",                        (void*)nAllocationData2D_i },
-{"rsnAllocationData2D",              "(IIIIIIII[SI)V",                        (void*)nAllocationData2D_s },
-{"rsnAllocationData2D",              "(IIIIIIII[BI)V",                        (void*)nAllocationData2D_b },
-{"rsnAllocationData2D",              "(IIIIIIII[FI)V",                        (void*)nAllocationData2D_f },
-{"rsnAllocationData2D",              "(IIIIIIIIIIIII)V",                      (void*)nAllocationData2D_alloc },
-{"rsnAllocationData3D",              "(IIIIIIIII[II)V",                       (void*)nAllocationData3D_i },
-{"rsnAllocationData3D",              "(IIIIIIIII[SI)V",                       (void*)nAllocationData3D_s },
-{"rsnAllocationData3D",              "(IIIIIIIII[BI)V",                       (void*)nAllocationData3D_b },
-{"rsnAllocationData3D",              "(IIIIIIIII[FI)V",                       (void*)nAllocationData3D_f },
-{"rsnAllocationData3D",              "(IIIIIIIIIIIIII)V",                     (void*)nAllocationData3D_alloc },
-{"rsnAllocationRead",                "(II[I)V",                               (void*)nAllocationRead_i },
-{"rsnAllocationRead",                "(II[S)V",                               (void*)nAllocationRead_s },
-{"rsnAllocationRead",                "(II[B)V",                               (void*)nAllocationRead_b },
-{"rsnAllocationRead",                "(II[F)V",                               (void*)nAllocationRead_f },
-{"rsnAllocationGetType",             "(II)I",                                 (void*)nAllocationGetType},
-{"rsnAllocationResize1D",            "(III)V",                                (void*)nAllocationResize1D },
-{"rsnAllocationGenerateMipmaps",     "(II)V",                                 (void*)nAllocationGenerateMipmaps },
-
-{"rsnScriptBindAllocation",          "(IIII)V",                               (void*)nScriptBindAllocation },
-{"rsnScriptSetTimeZone",             "(II[B)V",                               (void*)nScriptSetTimeZone },
-{"rsnScriptInvoke",                  "(III)V",                                (void*)nScriptInvoke },
-{"rsnScriptInvokeV",                 "(III[B)V",                              (void*)nScriptInvokeV },
-{"rsnScriptForEach",                 "(IIIII)V",                              (void*)nScriptForEach },
-{"rsnScriptForEach",                 "(IIIII[B)V",                            (void*)nScriptForEachV },
-{"rsnScriptForEachClipped",          "(IIIIIIIIIII)V",                        (void*)nScriptForEachClipped },
-{"rsnScriptForEachClipped",          "(IIIII[BIIIIII)V",                      (void*)nScriptForEachClippedV },
-{"rsnScriptSetVarI",                 "(IIII)V",                               (void*)nScriptSetVarI },
-{"rsnScriptGetVarI",                 "(III)I",                                (void*)nScriptGetVarI },
-{"rsnScriptSetVarJ",                 "(IIIJ)V",                               (void*)nScriptSetVarJ },
-{"rsnScriptGetVarJ",                 "(III)J",                                (void*)nScriptGetVarJ },
-{"rsnScriptSetVarF",                 "(IIIF)V",                               (void*)nScriptSetVarF },
-{"rsnScriptGetVarF",                 "(III)F",                                (void*)nScriptGetVarF },
-{"rsnScriptSetVarD",                 "(IIID)V",                               (void*)nScriptSetVarD },
-{"rsnScriptGetVarD",                 "(III)D",                                (void*)nScriptGetVarD },
-{"rsnScriptSetVarV",                 "(III[B)V",                              (void*)nScriptSetVarV },
-{"rsnScriptGetVarV",                 "(III[B)V",                              (void*)nScriptGetVarV },
-{"rsnScriptSetVarVE",                "(III[BI[I)V",                           (void*)nScriptSetVarVE },
-{"rsnScriptSetVarObj",               "(IIII)V",                               (void*)nScriptSetVarObj },
-
-{"rsnScriptCCreate",                 "(ILjava/lang/String;Ljava/lang/String;[BI)I",  (void*)nScriptCCreate },
-{"rsnScriptIntrinsicCreate",         "(III)I",                                (void*)nScriptIntrinsicCreate },
-{"rsnScriptKernelIDCreate",          "(IIII)I",                               (void*)nScriptKernelIDCreate },
-{"rsnScriptFieldIDCreate",           "(III)I",                                (void*)nScriptFieldIDCreate },
-{"rsnScriptGroupCreate",             "(I[I[I[I[I[I)I",                        (void*)nScriptGroupCreate },
-{"rsnScriptGroupSetInput",           "(IIII)V",                               (void*)nScriptGroupSetInput },
-{"rsnScriptGroupSetOutput",          "(IIII)V",                               (void*)nScriptGroupSetOutput },
-{"rsnScriptGroupExecute",            "(II)V",                                 (void*)nScriptGroupExecute },
-
-{"rsnProgramStoreCreate",            "(IZZZZZZIII)I",                         (void*)nProgramStoreCreate },
-
-{"rsnProgramBindConstants",          "(IIII)V",                               (void*)nProgramBindConstants },
-{"rsnProgramBindTexture",            "(IIII)V",                               (void*)nProgramBindTexture },
-{"rsnProgramBindSampler",            "(IIII)V",                               (void*)nProgramBindSampler },
-
-{"rsnProgramFragmentCreate",         "(ILjava/lang/String;[Ljava/lang/String;[I)I",              (void*)nProgramFragmentCreate },
-{"rsnProgramRasterCreate",           "(IZI)I",                                (void*)nProgramRasterCreate },
-{"rsnProgramVertexCreate",           "(ILjava/lang/String;[Ljava/lang/String;[I)I",              (void*)nProgramVertexCreate },
-
-{"rsnContextBindRootScript",         "(II)V",                                 (void*)nContextBindRootScript },
-{"rsnContextBindProgramStore",       "(II)V",                                 (void*)nContextBindProgramStore },
-{"rsnContextBindProgramFragment",    "(II)V",                                 (void*)nContextBindProgramFragment },
-{"rsnContextBindProgramVertex",      "(II)V",                                 (void*)nContextBindProgramVertex },
-{"rsnContextBindProgramRaster",      "(II)V",                                 (void*)nContextBindProgramRaster },
-
-{"rsnSamplerCreate",                 "(IIIIIIF)I",                            (void*)nSamplerCreate },
-
-{"rsnPathCreate",                    "(IIZIIF)I",                             (void*)nPathCreate },
-{"rsnMeshCreate",                    "(I[I[I[I)I",                            (void*)nMeshCreate },
-
-{"rsnMeshGetVertexBufferCount",      "(II)I",                                 (void*)nMeshGetVertexBufferCount },
-{"rsnMeshGetIndexCount",             "(II)I",                                 (void*)nMeshGetIndexCount },
-{"rsnMeshGetVertices",               "(II[II)V",                              (void*)nMeshGetVertices },
-{"rsnMeshGetIndices",                "(II[I[II)V",                            (void*)nMeshGetIndices },
-
-};
-
-static int registerFuncs(JNIEnv *_env)
-{
-    return android::AndroidRuntime::registerNativeMethods(
-            _env, classPathName, methods, NELEM(methods));
-}
-
-// ---------------------------------------------------------------------------
-
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
-{
-    JNIEnv* env = NULL;
-    jint result = -1;
-
-    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-        ALOGE("ERROR: GetEnv failed\n");
-        goto bail;
-    }
-    assert(env != NULL);
-
-    if (registerFuncs(env) < 0) {
-        ALOGE("ERROR: MediaPlayer native registration failed\n");
-        goto bail;
-    }
-
-    /* success -- return valid version number */
-    result = JNI_VERSION_1_4;
-
-bail:
-    return result;
-}
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index a010957..a13dd16 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -69,6 +69,13 @@
  */
 class AssetManager : public AAssetManager {
 public:
+    static const char* RESOURCES_FILENAME;
+    static const char* IDMAP_BIN;
+    static const char* OVERLAY_DIR;
+    static const char* TARGET_PACKAGE_NAME;
+    static const char* TARGET_APK_PATH;
+    static const char* IDMAP_DIR;
+
     typedef enum CacheMode {
         CACHE_UNKNOWN = 0,
         CACHE_OFF,          // don't try to cache file locations
@@ -93,6 +100,7 @@
      * newly-added asset source.
      */
     bool addAssetPath(const String8& path, int32_t* cookie);
+    bool addOverlayPath(const String8& path, int32_t* cookie);
 
     /*                                                                       
      * Convenience for adding the standard system assets.  Uses the
@@ -218,6 +226,13 @@
      */
     void getLocales(Vector<String8>* locales) const;
 
+    /**
+     * Generate idmap data to translate resources IDs between a package and a
+     * corresponding overlay package.
+     */
+    bool createIdmap(const char* targetApkPath, const char* overlayApkPath,
+        uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize);
+
 private:
     struct asset_path
     {
@@ -264,19 +279,14 @@
     void setLocaleLocked(const char* locale);
     void updateResourceParamsLocked() const;
 
-    bool createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
-                               const String8& idmapPath);
-
-    bool isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
-                            const String8& idmapPath);
-
     Asset* openIdmapLocked(const struct asset_path& ap) const;
 
-    bool getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, uint32_t* pCrc);
+    void addSystemOverlays(const char* pathOverlaysList, const String8& targetPackagePath,
+            ResTable* sharedRes, size_t offset) const;
 
     class SharedZip : public RefBase {
     public:
-        static sp<SharedZip> get(const String8& path);
+        static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true);
 
         ZipFileRO* getZip();
 
@@ -287,6 +297,9 @@
         ResTable* setResourceTable(ResTable* res);
         
         bool isUpToDate();
+
+        void addOverlay(const asset_path& ap);
+        bool getOverlay(size_t idx, asset_path* out) const;
         
     protected:
         ~SharedZip();
@@ -302,6 +315,8 @@
         Asset* mResourceTableAsset;
         ResTable* mResourceTable;
 
+        Vector<asset_path> mOverlays;
+
         static Mutex gLock;
         static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
     };
@@ -334,6 +349,9 @@
         static String8 getPathName(const char* path);
 
         bool isUpToDate();
+
+        void addOverlay(const String8& path, const asset_path& overlay);
+        bool getOverlay(const String8& path, size_t idx, asset_path* out) const;
         
     private:
         void closeZip(int idx);
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 5151b06..a0bae12 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -808,6 +808,19 @@
     uint32_t lastPublicKey;
 };
 
+// The most specific locale can consist of:
+//
+// - a 3 char language code
+// - a 3 char region code prefixed by a 'r'
+// - a 4 char script code prefixed by a 's'
+// - a 8 char variant code prefixed by a 'v'
+//
+// each separated by a single char separator, which sums up to a total of 24
+// chars, (25 include the string terminator) rounded up to 28 to be 4 byte
+// aligned.
+#define RESTABLE_MAX_LOCALE_LEN 28
+
+
 /**
  * Describes a particular resource configuration.
  */
@@ -828,10 +841,42 @@
     
     union {
         struct {
-            // \0\0 means "any".  Otherwise, en, fr, etc.
+            // This field can take three different forms:
+            // - \0\0 means "any".
+            //
+            // - Two 7 bit ascii values interpreted as ISO-639-1 language
+            //   codes ('fr', 'en' etc. etc.). The high bit for both bytes is
+            //   zero.
+            //
+            // - A single 16 bit little endian packed value representing an
+            //   ISO-639-2 3 letter language code. This will be of the form:
+            //
+            //   {1, t, t, t, t, t, s, s, s, s, s, f, f, f, f, f}
+            //
+            //   bit[0, 4] = first letter of the language code
+            //   bit[5, 9] = second letter of the language code
+            //   bit[10, 14] = third letter of the language code.
+            //   bit[15] = 1 always
+            //
+            // For backwards compatibility, languages that have unambiguous
+            // two letter codes are represented in that format.
+            //
+            // The layout is always bigendian irrespective of the runtime
+            // architecture.
             char language[2];
             
-            // \0\0 means "any".  Otherwise, US, CA, etc.
+            // This field can take three different forms:
+            // - \0\0 means "any".
+            //
+            // - Two 7 bit ascii values interpreted as 2 letter region
+            //   codes ('US', 'GB' etc.). The high bit for both bytes is zero.
+            //
+            // - An UN M.49 3 digit region code. For simplicity, these are packed
+            //   in the same manner as the language codes, though we should need
+            //   only 10 bits to represent them, instead of the 15.
+            //
+            // The layout is always bigendian irrespective of the runtime
+            // architecture.
             char country[2];
         };
         uint32_t locale;
@@ -933,7 +978,7 @@
         SDKVERSION_ANY = 0
     };
     
-    enum {
+  enum {
         MINORVERSION_ANY = 0
     };
     
@@ -1006,6 +1051,15 @@
         uint32_t screenSizeDp;
     };
 
+    // The ISO-15924 short name for the script corresponding to this
+    // configuration. (eg. Hant, Latn, etc.). Interpreted in conjunction with
+    // the locale field.
+    char localeScript[4];
+
+    // A single BCP-47 variant subtag. Will vary in length between 5 and 8
+    // chars. Interpreted in conjunction with the locale field.
+    char localeVariant[8];
+
     void copyFromDeviceNoSwap(const ResTable_config& o);
     
     void copyFromDtoH(const ResTable_config& o);
@@ -1063,7 +1117,46 @@
     // settings is the requested settings
     bool match(const ResTable_config& settings) const;
 
-    void getLocale(char str[6]) const;
+    // Get the string representation of the locale component of this
+    // Config. The maximum size of this representation will be
+    // |RESTABLE_MAX_LOCALE_LEN| (including a terminating '\0').
+    //
+    // Example: en-US, en-Latn-US, en-POSIX.
+    void getBcp47Locale(char* out) const;
+
+    // Sets the values of language, region, script and variant to the
+    // well formed BCP-47 locale contained in |in|. The input locale is
+    // assumed to be valid and no validation is performed.
+    void setBcp47Locale(const char* in);
+
+    inline void clearLocale() {
+        locale = 0;
+        memset(localeScript, 0, sizeof(localeScript));
+        memset(localeVariant, 0, sizeof(localeVariant));
+    }
+
+    // Get the 2 or 3 letter language code of this configuration. Trailing
+    // bytes are set to '\0'.
+    size_t unpackLanguage(char language[4]) const;
+    // Get the 2 or 3 letter language code of this configuration. Trailing
+    // bytes are set to '\0'.
+    size_t unpackRegion(char region[4]) const;
+
+    // Sets the language code of this configuration to the first three
+    // chars at |language|.
+    //
+    // If |language| is a 2 letter code, the trailing byte must be '\0' or
+    // the BCP-47 separator '-'.
+    void packLanguage(const char* language);
+    // Sets the region code of this configuration to the first three bytes
+    // at |region|. If |region| is a 2 letter code, the trailing byte must be '\0'
+    // or the BCP-47 separator '-'.
+    void packRegion(const char* region);
+
+    // Returns a positive integer if this config is more specific than |o|
+    // with respect to their locales, a negative integer if |o| is more specific
+    // and 0 if they're equally specific.
+    int isLocaleMoreSpecificThan(const ResTable_config &o) const;
 
     String8 toString() const;
 };
@@ -1279,14 +1372,13 @@
 {
 public:
     ResTable();
-    ResTable(const void* data, size_t size, void* cookie,
+    ResTable(const void* data, size_t size, const int32_t cookie,
              bool copyData=false);
     ~ResTable();
 
-    status_t add(const void* data, size_t size, void* cookie,
-                 bool copyData=false, const void* idmap = NULL);
-    status_t add(Asset* asset, void* cookie,
-                 bool copyData=false, const void* idmap = NULL);
+    status_t add(Asset* asset, const int32_t cookie, bool copyData,
+                 const void* idmap = NULL);
+    status_t add(const void *data, size_t size);
     status_t add(ResTable* src);
 
     status_t getError() const;
@@ -1534,7 +1626,7 @@
     // but not the names their entries or types.
     const ResStringPool* getTableStringBlock(size_t index) const;
     // Return unique cookie identifier for the given resource table.
-    void* getTableCookie(size_t index) const;
+    int32_t getTableCookie(size_t index) const;
 
     // Return the configurations (ResTable_config) that we know about
     void getConfigurations(Vector<ResTable_config>* configs) const;
@@ -1546,18 +1638,21 @@
     // Return value: on success: NO_ERROR; caller is responsible for free-ing
     // outData (using free(3)). On failure, any status_t value other than
     // NO_ERROR; the caller should not free outData.
-    status_t createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
-                         void** outData, size_t* outSize) const;
+    status_t createIdmap(const ResTable& overlay,
+            uint32_t targetCrc, uint32_t overlayCrc,
+            const char* targetPath, const char* overlayPath,
+            void** outData, size_t* outSize) const;
 
     enum {
-        IDMAP_HEADER_SIZE_BYTES = 3 * sizeof(uint32_t),
+        IDMAP_HEADER_SIZE_BYTES = 3 * sizeof(uint32_t) + 2 * 256,
     };
     // Retrieve idmap meta-data.
     //
     // This function only requires the idmap header (the first
     // IDMAP_HEADER_SIZE_BYTES) bytes of an idmap file.
     static bool getIdmapInfo(const void* idmap, size_t size,
-                             uint32_t* pOriginalCrc, uint32_t* pOverlayCrc);
+            uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+            String8* pTargetPath, String8* pOverlayPath);
 
     void print(bool inclValues) const;
     static String8 normalizeForOutput(const char* input);
@@ -1569,7 +1664,7 @@
     struct PackageGroup;
     struct bag_set;
 
-    status_t add(const void* data, size_t size, void* cookie,
+    status_t addInternal(const void* data, size_t size, const int32_t cookie,
                  Asset* asset, bool copyData, const Asset* idmap);
 
     ssize_t getResourcePackageIndex(uint32_t resID) const;
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 52ab361..b4d482a 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -41,10 +41,8 @@
 #include <assert.h>
 #include <dirent.h>
 #include <errno.h>
-#include <fcntl.h>
+#include <string.h> // strerror
 #include <strings.h>
-#include <sys/stat.h>
-#include <unistd.h>
 
 #ifndef TEMP_FAILURE_RETRY
 /* Used to retry syscalls that can return EINTR. */
@@ -75,7 +73,7 @@
 static const char* kAssetsRoot = "assets";
 static const char* kAppZipName = NULL; //"classes.jar";
 static const char* kSystemAssets = "framework/framework-res.apk";
-static const char* kIdmapCacheDir = "resource-cache";
+static const char* kResourceCache = "resource-cache";
 
 static const char* kExcludeExtension = ".EXCLUDE";
 
@@ -83,14 +81,20 @@
 
 static volatile int32_t gCount = 0;
 
+const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
+const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
+const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::TARGET_PACKAGE_NAME = "android";
+const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
+const char* AssetManager::IDMAP_DIR = "/data/resource-cache";
+
 namespace {
-    // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
     String8 idmapPathForPackagePath(const String8& pkgPath)
     {
         const char* root = getenv("ANDROID_DATA");
         LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
         String8 path(root);
-        path.appendPath(kIdmapCacheDir);
+        path.appendPath(kResourceCache);
 
         char buf[256]; // 256 chars should be enough for anyone...
         strncpy(buf, pkgPath.string(), 255);
@@ -208,180 +212,99 @@
         *cookie = static_cast<int32_t>(mAssetPaths.size());
     }
 
-    // add overlay packages for /system/framework; apps are handled by the
-    // (Java) package manager
-    if (strncmp(path.string(), "/system/framework/", 18) == 0) {
-        // When there is an environment variable for /vendor, this
-        // should be changed to something similar to how ANDROID_ROOT
-        // and ANDROID_DATA are used in this file.
-        String8 overlayPath("/vendor/overlay/framework/");
-        overlayPath.append(path.getPathLeaf());
-        if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) {
-            asset_path oap;
-            oap.path = overlayPath;
-            oap.type = ::getFileType(overlayPath.string());
-            bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay
-            if (addOverlay) {
-                oap.idmap = idmapPathForPackagePath(overlayPath);
-
-                if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) {
-                    addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap);
-                }
-            }
-            if (addOverlay) {
-                mAssetPaths.add(oap);
-            } else {
-                ALOGW("failed to add overlay package %s\n", overlayPath.string());
-            }
-        }
+#ifdef HAVE_ANDROID_OS
+    // Load overlays, if any
+    asset_path oap;
+    for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) {
+        mAssetPaths.add(oap);
     }
+#endif
 
     return true;
 }
 
-bool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
-                                      const String8& idmapPath)
+bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
 {
-    struct stat st;
-    if (TEMP_FAILURE_RETRY(stat(idmapPath.string(), &st)) == -1) {
-        if (errno == ENOENT) {
-            return true; // non-existing idmap is always stale
-        } else {
-            ALOGW("failed to stat file %s: %s\n", idmapPath.string(), strerror(errno));
-            return false;
-        }
-    }
-    if (st.st_size < ResTable::IDMAP_HEADER_SIZE_BYTES) {
-        ALOGW("file %s has unexpectedly small size=%zd\n", idmapPath.string(), (size_t)st.st_size);
-        return false;
-    }
-    int fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_RDONLY));
-    if (fd == -1) {
-        ALOGW("failed to open file %s: %s\n", idmapPath.string(), strerror(errno));
-        return false;
-    }
-    char buf[ResTable::IDMAP_HEADER_SIZE_BYTES];
-    ssize_t bytesLeft = ResTable::IDMAP_HEADER_SIZE_BYTES;
-    for (;;) {
-        ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf + ResTable::IDMAP_HEADER_SIZE_BYTES - bytesLeft,
-                                            bytesLeft));
-        if (r < 0) {
-            TEMP_FAILURE_RETRY(close(fd));
-            return false;
-        }
-        bytesLeft -= r;
-        if (bytesLeft == 0) {
-            break;
-        }
-    }
-    TEMP_FAILURE_RETRY(close(fd));
+    const String8 idmapPath = idmapPathForPackagePath(packagePath);
 
-    uint32_t cachedOriginalCrc, cachedOverlayCrc;
-    if (!ResTable::getIdmapInfo(buf, ResTable::IDMAP_HEADER_SIZE_BYTES,
-                                &cachedOriginalCrc, &cachedOverlayCrc)) {
+    AutoMutex _l(mLock);
+
+    for (size_t i = 0; i < mAssetPaths.size(); ++i) {
+        if (mAssetPaths[i].idmap == idmapPath) {
+           *cookie = static_cast<int32_t>(i + 1);
+            return true;
+         }
+     }
+
+    Asset* idmap = NULL;
+    if ((idmap = openAssetFromFileLocked(idmapPath, Asset::ACCESS_BUFFER)) == NULL) {
+        ALOGW("failed to open idmap file %s\n", idmapPath.string());
         return false;
     }
 
-    uint32_t actualOriginalCrc, actualOverlayCrc;
-    if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &actualOriginalCrc)) {
+    String8 targetPath;
+    String8 overlayPath;
+    if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
+                NULL, NULL, &targetPath, &overlayPath)) {
+        ALOGW("failed to read idmap file %s\n", idmapPath.string());
+        delete idmap;
         return false;
     }
-    if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &actualOverlayCrc)) {
-        return false;
-    }
-    return cachedOriginalCrc != actualOriginalCrc || cachedOverlayCrc != actualOverlayCrc;
-}
+    delete idmap;
 
-bool AssetManager::getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename,
-                                        uint32_t* pCrc)
+    if (overlayPath != packagePath) {
+        ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n",
+                idmapPath.string(), packagePath.string(), overlayPath.string());
+        return false;
+    }
+    if (access(targetPath.string(), R_OK) != 0) {
+        ALOGW("failed to access file %s: %s\n", targetPath.string(), strerror(errno));
+        return false;
+    }
+    if (access(idmapPath.string(), R_OK) != 0) {
+        ALOGW("failed to access file %s: %s\n", idmapPath.string(), strerror(errno));
+        return false;
+    }
+    if (access(overlayPath.string(), R_OK) != 0) {
+        ALOGW("failed to access file %s: %s\n", overlayPath.string(), strerror(errno));
+        return false;
+    }
+
+    asset_path oap;
+    oap.path = overlayPath;
+    oap.type = ::getFileType(overlayPath.string());
+    oap.idmap = idmapPath;
+#if 0
+    ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n",
+            targetPath.string(), overlayPath.string(), idmapPath.string());
+#endif
+    mAssetPaths.add(oap);
+    *cookie = static_cast<int32_t>(mAssetPaths.size());
+
+    return true;
+ }
+
+bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath,
+        uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize)
 {
-    asset_path ap;
-    ap.path = zipPath;
-    const ZipFileRO* zip = getZipFileLocked(ap);
-    if (zip == NULL) {
-        return false;
-    }
-    const ZipEntryRO entry = zip->findEntryByName(entryFilename);
-    if (entry == NULL) {
-        return false;
-    }
-
-    const bool gotInfo = zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)pCrc);
-    zip->releaseEntry(entry);
-
-    return gotInfo;
-}
-
-bool AssetManager::createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
-                                         const String8& idmapPath)
-{
-    ALOGD("%s: originalPath=%s overlayPath=%s idmapPath=%s\n",
-         __FUNCTION__, originalPath.string(), overlayPath.string(), idmapPath.string());
+    AutoMutex _l(mLock);
+    const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
     ResTable tables[2];
-    const String8* paths[2] = { &originalPath, &overlayPath };
-    uint32_t originalCrc, overlayCrc;
-    bool retval = false;
-    ssize_t offset = 0;
-    int fd = 0;
-    uint32_t* data = NULL;
-    size_t size;
 
     for (int i = 0; i < 2; ++i) {
         asset_path ap;
         ap.type = kFileTypeRegular;
-        ap.path = *paths[i];
+        ap.path = paths[i];
         Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
         if (ass == NULL) {
             ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
-            goto error;
+            return false;
         }
-        tables[i].add(ass, (void*)1, false);
+        tables[i].add(ass, 1, false /* copyData */, NULL /* idMap */);
     }
 
-    if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &originalCrc)) {
-        ALOGW("failed to retrieve crc for resources.arsc in %s\n", originalPath.string());
-        goto error;
-    }
-    if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &overlayCrc)) {
-        ALOGW("failed to retrieve crc for resources.arsc in %s\n", overlayPath.string());
-        goto error;
-    }
-
-    if (tables[0].createIdmap(tables[1], originalCrc, overlayCrc,
-                              (void**)&data, &size) != NO_ERROR) {
-        ALOGW("failed to generate idmap data for file %s\n", idmapPath.string());
-        goto error;
-    }
-
-    // This should be abstracted (eg replaced by a stand-alone
-    // application like dexopt, triggered by something equivalent to
-    // installd).
-    fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_WRONLY | O_CREAT | O_TRUNC, 0644));
-    if (fd == -1) {
-        ALOGW("failed to write idmap file %s (open: %s)\n", idmapPath.string(), strerror(errno));
-        goto error_free;
-    }
-    for (;;) {
-        ssize_t written = TEMP_FAILURE_RETRY(write(fd, data + offset, size));
-        if (written < 0) {
-            ALOGW("failed to write idmap file %s (write: %s)\n", idmapPath.string(),
-                 strerror(errno));
-            goto error_close;
-        }
-        size -= (size_t)written;
-        offset += written;
-        if (size == 0) {
-            break;
-        }
-    }
-
-    retval = true;
-error_close:
-    TEMP_FAILURE_RETRY(close(fd));
-error_free:
-    free(data);
-error:
-    return retval;
+    return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
+            targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
 }
 
 bool AssetManager::addDefaultAssets()
@@ -463,17 +386,8 @@
     if (locale) {
         setLocaleLocked(locale);
     } else if (config.language[0] != 0) {
-        char spec[9];
-        spec[0] = config.language[0];
-        spec[1] = config.language[1];
-        if (config.country[0] != 0) {
-            spec[2] = '_';
-            spec[3] = config.country[0];
-            spec[4] = config.country[1];
-            spec[5] = 0;
-        } else {
-            spec[3] = 0;
-        }
+        char spec[RESTABLE_MAX_LOCALE_LEN];
+        config.getBcp47Locale(spec);
         setLocaleLocked(spec);
     } else {
         updateResourceParamsLocked();
@@ -660,6 +574,10 @@
                 // which we want to avoid parsing every time.
                 sharedRes = const_cast<AssetManager*>(this)->
                     mZipSet.getZipResourceTable(ap.path);
+                if (sharedRes != NULL) {
+                    // skip ahead the number of system overlay packages preloaded
+                    i += sharedRes->getTableCount() - 1;
+                }
             }
             if (sharedRes == NULL) {
                 ass = const_cast<AssetManager*>(this)->
@@ -682,7 +600,15 @@
                     // can quickly copy it out for others.
                     ALOGV("Creating shared resources for %s", ap.path.string());
                     sharedRes = new ResTable();
-                    sharedRes->add(ass, (void*)(i+1), false, idmap);
+                    sharedRes->add(ass, i + 1, false, idmap);
+#ifdef HAVE_ANDROID_OS
+                    const char* data = getenv("ANDROID_DATA");
+                    LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
+                    String8 overlaysListPath(data);
+                    overlaysListPath.appendPath(kResourceCache);
+                    overlaysListPath.appendPath("overlays.list");
+                    addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, i);
+#endif
                     sharedRes = const_cast<AssetManager*>(this)->
                         mZipSet.setZipResourceTable(ap.path, sharedRes);
                 }
@@ -706,7 +632,7 @@
                 rt->add(sharedRes);
             } else {
                 ALOGV("Parsing resources for %s", ap.path.string());
-                rt->add(ass, (void*)(i+1), !shared, idmap);
+                rt->add(ass, i + 1, !shared, idmap);
             }
 
             if (!shared) {
@@ -733,20 +659,11 @@
         return;
     }
 
-    size_t llen = mLocale ? strlen(mLocale) : 0;
-    mConfig->language[0] = 0;
-    mConfig->language[1] = 0;
-    mConfig->country[0] = 0;
-    mConfig->country[1] = 0;
-    if (llen >= 2) {
-        mConfig->language[0] = mLocale[0];
-        mConfig->language[1] = mLocale[1];
+    if (mLocale) {
+        mConfig->setBcp47Locale(mLocale);
+    } else {
+        mConfig->clearLocale();
     }
-    if (llen >= 5) {
-        mConfig->country[0] = mLocale[3];
-        mConfig->country[1] = mLocale[4];
-    }
-    mConfig->size = sizeof(*mConfig);
 
     res->setParameters(mConfig);
 }
@@ -766,6 +683,46 @@
     return ass;
 }
 
+void AssetManager::addSystemOverlays(const char* pathOverlaysList,
+        const String8& targetPackagePath, ResTable* sharedRes, size_t offset) const
+{
+    FILE* fin = fopen(pathOverlaysList, "r");
+    if (fin == NULL) {
+        return;
+    }
+
+    char buf[1024];
+    while (fgets(buf, sizeof(buf), fin)) {
+        // format of each line:
+        //   <path to apk><space><path to idmap><newline>
+        char* space = strchr(buf, ' ');
+        char* newline = strchr(buf, '\n');
+        asset_path oap;
+
+        if (space == NULL || newline == NULL || newline < space) {
+            continue;
+        }
+
+        oap.path = String8(buf, space - buf);
+        oap.type = kFileTypeRegular;
+        oap.idmap = String8(space + 1, newline - space - 1);
+
+        Asset* oass = const_cast<AssetManager*>(this)->
+            openNonAssetInPathLocked("resources.arsc",
+                    Asset::ACCESS_BUFFER,
+                    oap);
+
+        if (oass != NULL) {
+            Asset* oidmap = openIdmapLocked(oap);
+            offset++;
+            sharedRes->add(oass, offset + 1, false, oidmap);
+            const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
+            const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
+        }
+    }
+    fclose(fin);
+}
+
 const ResTable& AssetManager::getResources(bool required) const
 {
     const ResTable* rt = getResTable(required);
@@ -1824,7 +1781,8 @@
     }
 }
 
-sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path)
+sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path,
+        bool createIfNotPresent)
 {
     AutoMutex _l(gLock);
     time_t modWhen = getFileModDate(path);
@@ -1832,6 +1790,9 @@
     if (zip != NULL && zip->mModWhen == modWhen) {
         return zip;
     }
+    if (zip == NULL && !createIfNotPresent) {
+        return NULL;
+    }
     zip = new SharedZip(path, modWhen);
     gOpen.add(path, zip);
     return zip;
@@ -1890,6 +1851,20 @@
     return mModWhen == modWhen;
 }
 
+void AssetManager::SharedZip::addOverlay(const asset_path& ap)
+{
+    mOverlays.add(ap);
+}
+
+bool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const
+{
+    if (idx >= mOverlays.size()) {
+        return false;
+    }
+    *out = mOverlays[idx];
+    return true;
+}
+
 AssetManager::SharedZip::~SharedZip()
 {
     //ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath);
@@ -2013,6 +1988,22 @@
     return true;
 }
 
+void AssetManager::ZipSet::addOverlay(const String8& path, const asset_path& overlay)
+{
+    int idx = getIndex(path);
+    sp<SharedZip> zip = mZipFile[idx];
+    zip->addOverlay(overlay);
+}
+
+bool AssetManager::ZipSet::getOverlay(const String8& path, size_t idx, asset_path* out) const
+{
+    sp<SharedZip> zip = SharedZip::get(path, false);
+    if (zip == NULL) {
+        return false;
+    }
+    return zip->getOverlay(idx, out);
+}
+
 /*
  * Compute the zip file's index.
  *
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 1cc3563..51f59f6 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -66,11 +66,6 @@
 // size measured in sizeof(uint32_t)
 #define IDMAP_HEADER_SIZE (ResTable::IDMAP_HEADER_SIZE_BYTES / sizeof(uint32_t))
 
-static void printToLogFunc(void* cookie, const char* txt)
-{
-    ALOGV("%s", txt);
-}
-
 // Standard C isspace() is only required to look at the low byte of its input, so
 // produces incorrect results for UTF-16 characters.  For safety's sake, assume that
 // any high-byte UTF-16 code point is not whitespace.
@@ -106,21 +101,20 @@
                 if ((ssize_t)size <= (dataEnd-((const uint8_t*)chunk))) {
                     return NO_ERROR;
                 }
-                ALOGW("%s data size %p extends beyond resource end %p.",
-                     name, (void*)size,
-                     (void*)(dataEnd-((const uint8_t*)chunk)));
+                ALOGW("%s data size 0x%x extends beyond resource end %p.",
+                     name, size, (void*)(dataEnd-((const uint8_t*)chunk)));
                 return BAD_TYPE;
             }
             ALOGW("%s size 0x%x or headerSize 0x%x is not on an integer boundary.",
                  name, (int)size, (int)headerSize);
             return BAD_TYPE;
         }
-        ALOGW("%s size %p is smaller than header size %p.",
-             name, (void*)size, (void*)(int)headerSize);
+        ALOGW("%s size 0x%x is smaller than header size 0x%x.",
+             name, size, headerSize);
         return BAD_TYPE;
     }
-    ALOGW("%s header size %p is too small.",
-         name, (void*)(int)headerSize);
+    ALOGW("%s header size 0x%x is too small.",
+         name, headerSize);
     return BAD_TYPE;
 }
 
@@ -284,11 +278,37 @@
     if (!assertIdmapHeader(map, mapSize)) {
         return UNKNOWN_ERROR;
     }
+    if (mapSize <= IDMAP_HEADER_SIZE + 1) {
+        ALOGW("corrupt idmap: map size %d too short\n", mapSize);
+        return UNKNOWN_ERROR;
+    }
+    uint32_t typeCount = *(map + IDMAP_HEADER_SIZE);
+    if (typeCount == 0) {
+        ALOGW("corrupt idmap: no types\n");
+        return UNKNOWN_ERROR;
+    }
+    if (IDMAP_HEADER_SIZE + 1 + typeCount > mapSize) {
+        ALOGW("corrupt idmap: number of types %d extends past idmap size %d\n", typeCount, mapSize);
+        return UNKNOWN_ERROR;
+    }
     const uint32_t* p = map + IDMAP_HEADER_SIZE + 1;
+    // find first defined type
     while (*p == 0) {
         ++p;
+        if (--typeCount == 0) {
+            ALOGW("corrupt idmap: types declared, none found\n");
+            return UNKNOWN_ERROR;
+        }
     }
-    *outId = (map[*p + IDMAP_HEADER_SIZE + 2] >> 24) & 0x000000ff;
+
+    // determine package id from first entry of first type
+    const uint32_t offset = *p + IDMAP_HEADER_SIZE + 2;
+    if (offset > mapSize) {
+        ALOGW("corrupt idmap: entry offset %d points outside map size %d\n", offset, mapSize);
+        return UNKNOWN_ERROR;
+    }
+    *outId = (map[offset] >> 24) & 0x000000ff;
+
     return NO_ERROR;
 }
 
@@ -1539,6 +1559,71 @@
     }
 }
 
+/* static */ size_t unpackLanguageOrRegion(const char in[2], const char base,
+        char out[4]) {
+  if (in[0] & 0x80) {
+      // The high bit is "1", which means this is a packed three letter
+      // language code.
+
+      // The smallest 5 bits of the second char are the first alphabet.
+      const uint8_t first = in[1] & 0x1f;
+      // The last three bits of the second char and the first two bits
+      // of the first char are the second alphabet.
+      const uint8_t second = ((in[1] & 0xe0) >> 5) + ((in[0] & 0x03) << 3);
+      // Bits 3 to 7 (inclusive) of the first char are the third alphabet.
+      const uint8_t third = (in[0] & 0x7c) >> 2;
+
+      out[0] = first + base;
+      out[1] = second + base;
+      out[2] = third + base;
+      out[3] = 0;
+
+      return 3;
+  }
+
+  if (in[0]) {
+      memcpy(out, in, 2);
+      memset(out + 2, 0, 2);
+      return 2;
+  }
+
+  memset(out, 0, 4);
+  return 0;
+}
+
+/* static */ void packLanguageOrRegion(const char* in, const char base,
+        char out[2]) {
+  if (in[2] == 0 || in[2] == '-') {
+      out[0] = in[0];
+      out[1] = in[1];
+  } else {
+      uint8_t first = (in[0] - base) & 0x00ef;
+      uint8_t second = (in[1] - base) & 0x00ef;
+      uint8_t third = (in[2] - base) & 0x00ef;
+
+      out[0] = (0x80 | (third << 2) | (second >> 3));
+      out[1] = ((second << 5) | first);
+  }
+}
+
+
+void ResTable_config::packLanguage(const char* language) {
+    packLanguageOrRegion(language, 'a', this->language);
+}
+
+void ResTable_config::packRegion(const char* region) {
+    packLanguageOrRegion(region, '0', this->country);
+}
+
+size_t ResTable_config::unpackLanguage(char language[4]) const {
+    return unpackLanguageOrRegion(this->language, 'a', language);
+}
+
+size_t ResTable_config::unpackRegion(char region[4]) const {
+    return unpackLanguageOrRegion(this->country, '0', region);
+}
+
+
 void ResTable_config::copyFromDtoH(const ResTable_config& o) {
     copyFromDeviceNoSwap(o);
     size = sizeof(ResTable_config);
@@ -1568,10 +1653,30 @@
     screenHeightDp = htods(screenHeightDp);
 }
 
+/* static */ inline int compareLocales(const ResTable_config &l, const ResTable_config &r) {
+    if (l.locale != r.locale) {
+        // NOTE: This is the old behaviour with respect to comparison orders.
+        // The diff value here doesn't make much sense (given our bit packing scheme)
+        // but it's stable, and that's all we need.
+        return l.locale - r.locale;
+    }
+
+    // The language & region are equal, so compare the scripts and variants.
+    int script = memcmp(l.localeScript, r.localeScript, sizeof(l.localeScript));
+    if (script) {
+        return script;
+    }
+
+    // The language, region and script are equal, so compare variants.
+    //
+    // This should happen very infrequently (if at all.)
+    return memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant));
+}
+
 int ResTable_config::compare(const ResTable_config& o) const {
     int32_t diff = (int32_t)(imsi - o.imsi);
     if (diff != 0) return diff;
-    diff = (int32_t)(locale - o.locale);
+    diff = compareLocales(*this, o);
     if (diff != 0) return diff;
     diff = (int32_t)(screenType - o.screenType);
     if (diff != 0) return diff;
@@ -1598,18 +1703,15 @@
     if (mnc != o.mnc) {
         return mnc < o.mnc ? -1 : 1;
     }
-    if (language[0] != o.language[0]) {
-        return language[0] < o.language[0] ? -1 : 1;
+
+    int diff = compareLocales(*this, o);
+    if (diff < 0) {
+        return -1;
     }
-    if (language[1] != o.language[1]) {
-        return language[1] < o.language[1] ? -1 : 1;
+    if (diff > 0) {
+        return 1;
     }
-    if (country[0] != o.country[0]) {
-        return country[0] < o.country[0] ? -1 : 1;
-    }
-    if (country[1] != o.country[1]) {
-        return country[1] < o.country[1] ? -1 : 1;
-    }
+
     if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) {
         return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayout & MASK_LAYOUTDIR) ? -1 : 1;
     }
@@ -1656,7 +1758,6 @@
     int diffs = 0;
     if (mcc != o.mcc) diffs |= CONFIG_MCC;
     if (mnc != o.mnc) diffs |= CONFIG_MNC;
-    if (locale != o.locale) diffs |= CONFIG_LOCALE;
     if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
     if (density != o.density) diffs |= CONFIG_DENSITY;
     if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
@@ -1671,9 +1772,44 @@
     if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
     if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
     if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
+
+    const int diff = compareLocales(*this, o);
+    if (diff) diffs |= CONFIG_LOCALE;
+
     return diffs;
 }
 
+int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const {
+    if (locale || o.locale) {
+        if (language[0] != o.language[0]) {
+            if (!language[0]) return -1;
+            if (!o.language[0]) return 1;
+        }
+
+        if (country[0] != o.country[0]) {
+            if (!country[0]) return -1;
+            if (!o.country[0]) return 1;
+        }
+    }
+
+    // There isn't a well specified "importance" order between variants and
+    // scripts. We can't easily tell whether, say "en-Latn-US" is more or less
+    // specific than "en-US-POSIX".
+    //
+    // We therefore arbitrarily decide to give priority to variants over
+    // scripts since it seems more useful to do so. We will consider
+    // "en-US-POSIX" to be more specific than "en-Latn-US".
+
+    const int score = ((localeScript[0] != 0) ? 1 : 0) +
+        ((localeVariant[0] != 0) ? 2 : 0);
+
+    const int oScore = ((o.localeScript[0] != 0) ? 1 : 0) +
+        ((o.localeVariant[0] != 0) ? 2 : 0);
+
+    return score - oScore;
+
+}
+
 bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const {
     // The order of the following tests defines the importance of one
     // configuration parameter over another.  Those tests first are more
@@ -1691,14 +1827,13 @@
     }
 
     if (locale || o.locale) {
-        if (language[0] != o.language[0]) {
-            if (!language[0]) return false;
-            if (!o.language[0]) return true;
+        const int diff = isLocaleMoreSpecificThan(o);
+        if (diff < 0) {
+            return false;
         }
 
-        if (country[0] != o.country[0]) {
-            if (!country[0]) return false;
-            if (!o.country[0]) return true;
+        if (diff > 0) {
+            return true;
         }
     }
 
@@ -1834,6 +1969,18 @@
             }
         }
 
+        if (localeScript[0] || o.localeScript[0]) {
+            if (localeScript[0] != o.localeScript[0] && requested->localeScript[0]) {
+                return localeScript[0];
+            }
+        }
+
+        if (localeVariant[0] || o.localeVariant[0]) {
+            if (localeVariant[0] != o.localeVariant[0] && requested->localeVariant[0]) {
+                return localeVariant[0];
+            }
+        }
+
         if (screenLayout || o.screenLayout) {
             if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0
                     && (requested->screenLayout & MASK_LAYOUTDIR)) {
@@ -2054,17 +2201,23 @@
         }
     }
     if (locale != 0) {
+        // Don't consider the script & variants when deciding matches.
+        //
+        // If we two configs differ only in their script or language, they
+        // can be weeded out in the isMoreSpecificThan test.
         if (language[0] != 0
             && (language[0] != settings.language[0]
                 || language[1] != settings.language[1])) {
             return false;
         }
+
         if (country[0] != 0
             && (country[0] != settings.country[0]
                 || country[1] != settings.country[1])) {
             return false;
         }
     }
+
     if (screenConfig != 0) {
         const int layoutDir = screenLayout&MASK_LAYOUTDIR;
         const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR;
@@ -2166,17 +2319,92 @@
     return true;
 }
 
-void ResTable_config::getLocale(char str[6]) const {
-    memset(str, 0, 6);
-    if (language[0]) {
-        str[0] = language[0];
-        str[1] = language[1];
-        if (country[0]) {
-            str[2] = '_';
-            str[3] = country[0];
-            str[4] = country[1];
-        }
+void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN]) const {
+    memset(str, 0, RESTABLE_MAX_LOCALE_LEN);
+
+    // This represents the "any" locale value, which has traditionally been
+    // represented by the empty string.
+    if (!language[0] && !country[0]) {
+        return;
     }
+
+    size_t charsWritten = 0;
+    if (language[0]) {
+        charsWritten += unpackLanguage(str);
+    }
+
+    if (localeScript[0]) {
+        if (charsWritten) {
+            str[charsWritten++] = '-';
+        }
+        memcpy(str + charsWritten, localeScript, sizeof(localeScript));
+        charsWritten += sizeof(localeScript);
+    }
+
+    if (country[0]) {
+        if (charsWritten) {
+            str[charsWritten++] = '-';
+        }
+        charsWritten += unpackRegion(str + charsWritten);
+    }
+
+    if (localeVariant[0]) {
+        if (charsWritten) {
+            str[charsWritten++] = '-';
+        }
+        memcpy(str + charsWritten, localeVariant, sizeof(localeVariant));
+    }
+}
+
+/* static */ inline bool assignLocaleComponent(ResTable_config* config,
+        const char* start, size_t size) {
+
+  switch (size) {
+       case 0:
+           return false;
+       case 2:
+       case 3:
+           config->language[0] ? config->packRegion(start) : config->packLanguage(start);
+           break;
+       case 4:
+           config->localeScript[0] = toupper(start[0]);
+           for (size_t i = 1; i < 4; ++i) {
+               config->localeScript[i] = tolower(start[i]);
+           }
+           break;
+       case 5:
+       case 6:
+       case 7:
+       case 8:
+           for (size_t i = 0; i < size; ++i) {
+               config->localeVariant[i] = tolower(start[i]);
+           }
+           break;
+       default:
+           return false;
+  }
+
+  return true;
+}
+
+void ResTable_config::setBcp47Locale(const char* in) {
+    locale = 0;
+    memset(localeScript, 0, sizeof(localeScript));
+    memset(localeVariant, 0, sizeof(localeVariant));
+
+    const char* separator = in;
+    const char* start = in;
+    while ((separator = strchr(start, '-')) != NULL) {
+        const size_t size = separator - start;
+        if (!assignLocaleComponent(this, start, size)) {
+            fprintf(stderr, "Invalid BCP-47 locale string: %s", in);
+        }
+
+        start = (separator + 1);
+    }
+
+    const size_t size = in + strlen(in) - start;
+    assignLocaleComponent(this, start, size);
 }
 
 String8 ResTable_config::toString() const {
@@ -2190,14 +2418,10 @@
         if (res.size() > 0) res.append("-");
         res.appendFormat("%dmnc", dtohs(mnc));
     }
-    if (language[0] != 0) {
-        if (res.size() > 0) res.append("-");
-        res.append(language, 2);
-    }
-    if (country[0] != 0) {
-        if (res.size() > 0) res.append("-");
-        res.append(country, 2);
-    }
+    char localeStr[RESTABLE_MAX_LOCALE_LEN];
+    getBcp47Locale(localeStr);
+    res.append(localeStr);
+
     if ((screenLayout&MASK_LAYOUTDIR) != 0) {
         if (res.size() > 0) res.append("-");
         switch (screenLayout&ResTable_config::MASK_LAYOUTDIR) {
@@ -2461,7 +2685,7 @@
     size_t                          size;
     const uint8_t*                  dataEnd;
     size_t                          index;
-    void*                           cookie;
+    int32_t                         cookie;
 
     ResStringPool                   values;
     uint32_t*                       resourceIDMap;
@@ -2860,12 +3084,12 @@
     //ALOGI("Creating ResTable %p\n", this);
 }
 
-ResTable::ResTable(const void* data, size_t size, void* cookie, bool copyData)
+ResTable::ResTable(const void* data, size_t size, const int32_t cookie, bool copyData)
     : mError(NO_INIT)
 {
     memset(&mParams, 0, sizeof(mParams));
     memset(mPackageMap, 0, sizeof(mPackageMap));
-    add(data, size, cookie, copyData);
+    addInternal(data, size, cookie, NULL /* asset */, copyData, NULL /* idMap */);
     LOG_FATAL_IF(mError != NO_ERROR, "Error parsing resource table");
     //ALOGI("Creating ResTable %p\n", this);
 }
@@ -2881,13 +3105,12 @@
     return ((ssize_t)mPackageMap[Res_GETPACKAGE(resID)+1])-1;
 }
 
-status_t ResTable::add(const void* data, size_t size, void* cookie, bool copyData,
-                       const void* idmap)
-{
-    return add(data, size, cookie, NULL, copyData, reinterpret_cast<const Asset*>(idmap));
+status_t ResTable::add(const void* data, size_t size) {
+    return addInternal(data, size, 0 /* cookie */, NULL /* asset */,
+            false /* copyData */, NULL /* idMap */);
 }
 
-status_t ResTable::add(Asset* asset, void* cookie, bool copyData, const void* idmap)
+status_t ResTable::add(Asset* asset, const int32_t cookie, bool copyData, const void* idmap)
 {
     const void* data = asset->getBuffer(true);
     if (data == NULL) {
@@ -2895,7 +3118,8 @@
         return UNKNOWN_ERROR;
     }
     size_t size = (size_t)asset->getLength();
-    return add(data, size, cookie, asset, copyData, reinterpret_cast<const Asset*>(idmap));
+    return addInternal(data, size, cookie, asset, copyData,
+            reinterpret_cast<const Asset*>(idmap));
 }
 
 status_t ResTable::add(ResTable* src)
@@ -2922,7 +3146,7 @@
     return mError;
 }
 
-status_t ResTable::add(const void* data, size_t size, void* cookie,
+status_t ResTable::addInternal(const void* data, size_t size, const int32_t cookie,
                        Asset* asset, bool copyData, const Asset* idmap)
 {
     if (!data) return NO_ERROR;
@@ -2945,7 +3169,7 @@
     const bool notDeviceEndian = htods(0xf0) != 0xf0;
 
     LOAD_TABLE_NOISY(
-        ALOGV("Adding resources to ResTable: data=%p, size=0x%x, cookie=%p, asset=%p, copy=%d "
+        ALOGV("Adding resources to ResTable: data=%p, size=0x%x, cookie=%d, asset=%p, copy=%d "
              "idmap=%p\n", data, size, cookie, asset, copyData, idmap));
     
     if (copyData || notDeviceEndian) {
@@ -3027,8 +3251,8 @@
             }
             curPackage++;
         } else {
-            ALOGW("Unknown chunk type %p in table at %p.\n",
-                 (void*)(int)(ctype),
+            ALOGW("Unknown chunk type 0x%x in table at %p.\n",
+                 ctype,
                  (void*)(((const uint8_t*)chunk) - ((const uint8_t*)header->header)));
         }
         chunk = (const ResChunk_header*)
@@ -3244,8 +3468,8 @@
 
         if ((dtohs(entry->flags)&entry->FLAG_COMPLEX) != 0) {
             if (!mayBeBag) {
-                ALOGW("Requesting resource %p failed because it is complex\n",
-                     (void*)resID);
+                ALOGW("Requesting resource 0x%x failed because it is complex\n",
+                     resID);
             }
             continue;
         }
@@ -3520,8 +3744,8 @@
         }
 
         if ((dtohs(entry->flags)&entry->FLAG_COMPLEX) == 0) {
-            ALOGW("Skipping entry %p in package table %d because it is not complex!\n",
-                 (void*)resID, (int)ip);
+            ALOGW("Skipping entry 0x%x in package table %zu because it is not complex!\n",
+                 resID, ip);
             continue;
         }
 
@@ -4930,7 +5154,7 @@
     return &mHeaders[index]->values;
 }
 
-void* ResTable::getTableCookie(size_t index) const
+int32_t ResTable::getTableCookie(size_t index) const
 {
     return mHeaders[index]->cookie;
 }
@@ -4950,18 +5174,20 @@
                 const size_t L = type->configs.size();
                 for (size_t l=0; l<L; l++) {
                     const ResTable_type* config = type->configs[l];
-                    const ResTable_config* cfg = &config->config;
+                    ResTable_config cfg;
+                    memset(&cfg, 0, sizeof(ResTable_config));
+                    cfg.copyFromDtoH(config->config);
                     // only insert unique
                     const size_t M = configs->size();
                     size_t m;
                     for (m=0; m<M; m++) {
-                        if (0 == (*configs)[m].compare(*cfg)) {
+                        if (0 == (*configs)[m].compare(cfg)) {
                             break;
                         }
                     }
                     // if we didn't find it
                     if (m == M) {
-                        configs->add(*cfg);
+                        configs->add(cfg);
                     }
                 }
             }
@@ -4976,9 +5202,10 @@
     getConfigurations(&configs);
     ALOGV("called getConfigurations size=%d", (int)configs.size());
     const size_t I = configs.size();
+
+    char locale[RESTABLE_MAX_LOCALE_LEN];
     for (size_t i=0; i<I; i++) {
-        char locale[6];
-        configs[i].getLocale(locale);
+        configs[i].getBcp47Locale(locale);
         const size_t J = locales->size();
         size_t j;
         for (j=0; j<J; j++) {
@@ -5114,26 +5341,26 @@
         return (mError=err);
     }
 
-    const size_t pkgSize = dtohl(pkg->header.size);
+    const uint32_t pkgSize = dtohl(pkg->header.size);
 
     if (dtohl(pkg->typeStrings) >= pkgSize) {
-        ALOGW("ResTable_package type strings at %p are past chunk size %p.",
-             (void*)dtohl(pkg->typeStrings), (void*)pkgSize);
+        ALOGW("ResTable_package type strings at 0x%x are past chunk size 0x%x.",
+             dtohl(pkg->typeStrings), pkgSize);
         return (mError=BAD_TYPE);
     }
     if ((dtohl(pkg->typeStrings)&0x3) != 0) {
-        ALOGW("ResTable_package type strings at %p is not on an integer boundary.",
-             (void*)dtohl(pkg->typeStrings));
+        ALOGW("ResTable_package type strings at 0x%x is not on an integer boundary.",
+             dtohl(pkg->typeStrings));
         return (mError=BAD_TYPE);
     }
     if (dtohl(pkg->keyStrings) >= pkgSize) {
-        ALOGW("ResTable_package key strings at %p are past chunk size %p.",
-             (void*)dtohl(pkg->keyStrings), (void*)pkgSize);
+        ALOGW("ResTable_package key strings at 0x%x are past chunk size 0x%x.",
+             dtohl(pkg->keyStrings), pkgSize);
         return (mError=BAD_TYPE);
     }
     if ((dtohl(pkg->keyStrings)&0x3) != 0) {
-        ALOGW("ResTable_package key strings at %p is not on an integer boundary.",
-             (void*)dtohl(pkg->keyStrings));
+        ALOGW("ResTable_package key strings at 0x%x is not on an integer boundary.",
+             dtohl(pkg->keyStrings));
         return (mError=BAD_TYPE);
     }
     
@@ -5271,7 +5498,7 @@
                 return (mError=err);
             }
             
-            const size_t typeSize = dtohl(type->header.size);
+            const uint32_t typeSize = dtohl(type->header.size);
             
             LOAD_TABLE_NOISY(printf("Type off %p: type=0x%x, headerSize=0x%x, size=%p\n",
                                     (void*)(base-(const uint8_t*)chunk),
@@ -5280,16 +5507,16 @@
                                     (void*)typeSize));
             if (dtohs(type->header.headerSize)+(sizeof(uint32_t)*dtohl(type->entryCount))
                 > typeSize) {
-                ALOGW("ResTable_type entry index to %p extends beyond chunk end %p.",
+                ALOGW("ResTable_type entry index to %p extends beyond chunk end 0x%x.",
                      (void*)(dtohs(type->header.headerSize)
                              +(sizeof(uint32_t)*dtohl(type->entryCount))),
-                     (void*)typeSize);
+                     typeSize);
                 return (mError=BAD_TYPE);
             }
             if (dtohl(type->entryCount) != 0
                 && dtohl(type->entriesStart) > (typeSize-sizeof(ResTable_entry))) {
-                ALOGW("ResTable_type entriesStart at %p extends beyond chunk end %p.",
-                     (void*)dtohl(type->entriesStart), (void*)typeSize);
+                ALOGW("ResTable_type entriesStart at 0x%x extends beyond chunk end 0x%x.",
+                     dtohl(type->entriesStart), typeSize);
                 return (mError=BAD_TYPE);
             }
             if (type->id == 0) {
@@ -5334,23 +5561,30 @@
     return NO_ERROR;
 }
 
-status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
-                               void** outData, size_t* outSize) const
+status_t ResTable::createIdmap(const ResTable& overlay,
+        uint32_t targetCrc, uint32_t overlayCrc,
+        const char* targetPath, const char* overlayPath,
+        void** outData, size_t* outSize) const
 {
     // see README for details on the format of map
     if (mPackageGroups.size() == 0) {
+        ALOGW("idmap: target package has no package groups, cannot create idmap\n");
         return UNKNOWN_ERROR;
     }
     if (mPackageGroups[0]->packages.size() == 0) {
+        ALOGW("idmap: target package has no packages in its first package group, "
+                "cannot create idmap\n");
         return UNKNOWN_ERROR;
     }
 
     Vector<Vector<uint32_t> > map;
+    // overlaid packages are assumed to contain only one package group
     const PackageGroup* pg = mPackageGroups[0];
     const Package* pkg = pg->packages[0];
     size_t typeCount = pkg->types.size();
     // starting size is header + first item (number of types in map)
     *outSize = (IDMAP_HEADER_SIZE + 1) * sizeof(uint32_t);
+    // overlay packages are assumed to contain only one package group
     const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name);
     const uint32_t pkg_id = pkg->package->id << 24;
 
@@ -5368,7 +5602,7 @@
                 | (0x00ff0000 & ((typeIndex+1)<<16))
                 | (0x0000ffff & (entryIndex));
             resource_name resName;
-            if (!this->getResourceName(resID, true, &resName)) {
+            if (!this->getResourceName(resID, false, &resName)) {
                 ALOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID);
                 // add dummy value, or trimming leading/trailing zeroes later will fail
                 vector.push(0);
@@ -5426,8 +5660,22 @@
     }
     uint32_t* data = (uint32_t*)*outData;
     *data++ = htodl(IDMAP_MAGIC);
-    *data++ = htodl(originalCrc);
+    *data++ = htodl(targetCrc);
     *data++ = htodl(overlayCrc);
+    const char* paths[] = { targetPath, overlayPath };
+    for (int j = 0; j < 2; ++j) {
+        char* p = (char*)data;
+        const char* path = paths[j];
+        const size_t I = strlen(path);
+        if (I > 255) {
+            ALOGV("path exceeds expected 255 characters: %s\n", path);
+            return UNKNOWN_ERROR;
+        }
+        for (size_t i = 0; i < 256; ++i) {
+            *p++ = i < I ? path[i] : '\0';
+        }
+        data += 256 / sizeof(uint32_t);
+    }
     const size_t mapSize = map.size();
     *data++ = htodl(mapSize);
     size_t offset = mapSize;
@@ -5442,6 +5690,10 @@
             offset += N;
         }
     }
+    if (offset == mapSize) {
+        ALOGW("idmap: no resources in overlay package present in base package\n");
+        return UNKNOWN_ERROR;
+    }
     for (size_t i = 0; i < mapSize; ++i) {
         const Vector<uint32_t>& vector = map.itemAt(i);
         const size_t N = vector.size();
@@ -5463,14 +5715,25 @@
 }
 
 bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
-                            uint32_t* pOriginalCrc, uint32_t* pOverlayCrc)
+                            uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+                            String8* pTargetPath, String8* pOverlayPath)
 {
     const uint32_t* map = (const uint32_t*)idmap;
     if (!assertIdmapHeader(map, sizeBytes)) {
         return false;
     }
-    *pOriginalCrc = map[1];
-    *pOverlayCrc = map[2];
+    if (pTargetCrc) {
+        *pTargetCrc = map[1];
+    }
+    if (pOverlayCrc) {
+        *pOverlayCrc = map[2];
+    }
+    if (pTargetPath) {
+        pTargetPath->setTo(reinterpret_cast<const char*>(map + 3));
+    }
+    if (pOverlayPath) {
+        pOverlayPath->setTo(reinterpret_cast<const char*>(map + 3 + 256 / sizeof(uint32_t)));
+    }
     return true;
 }
 
@@ -5601,9 +5864,9 @@
         printf("mError=0x%x (%s)\n", mError, strerror(mError));
     }
 #if 0
-    printf("mParams=%c%c-%c%c,\n",
-            mParams.language[0], mParams.language[1],
-            mParams.country[0], mParams.country[1]);
+    char localeStr[RESTABLE_MAX_LOCALE_LEN];
+    mParams.getBcp47Locale(localeStr);
+    printf("mParams=%s,\n" localeStr);
 #endif
     size_t pgCount = mPackageGroups.size();
     printf("Package Groups (%d)\n", (int)pgCount);
@@ -5670,12 +5933,12 @@
                     size_t entryCount = dtohl(type->entryCount);
                     uint32_t entriesStart = dtohl(type->entriesStart);
                     if ((entriesStart&0x3) != 0) {
-                        printf("      NON-INTEGER ResTable_type entriesStart OFFSET: %p\n", (void*)entriesStart);
+                        printf("      NON-INTEGER ResTable_type entriesStart OFFSET: 0x%x\n", entriesStart);
                         continue;
                     }
                     uint32_t typeSize = dtohl(type->header.size);
                     if ((typeSize&0x3) != 0) {
-                        printf("      NON-INTEGER ResTable_type header.size: %p\n", (void*)typeSize);
+                        printf("      NON-INTEGER ResTable_type header.size: 0x%x\n", typeSize);
                         continue;
                     }
                     for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) {
@@ -5714,33 +5977,31 @@
                             printf("        INVALID RESOURCE 0x%08x: ", resID);
                         }
                         if ((thisOffset&0x3) != 0) {
-                            printf("NON-INTEGER OFFSET: %p\n", (void*)thisOffset);
+                            printf("NON-INTEGER OFFSET: 0x%x\n", thisOffset);
                             continue;
                         }
                         if ((thisOffset+sizeof(ResTable_entry)) > typeSize) {
-                            printf("OFFSET OUT OF BOUNDS: %p+%p (size is %p)\n",
-                                   (void*)entriesStart, (void*)thisOffset,
-                                   (void*)typeSize);
+                            printf("OFFSET OUT OF BOUNDS: 0x%x+0x%x (size is 0x%x)\n",
+                                   entriesStart, thisOffset, typeSize);
                             continue;
                         }
                         
                         const ResTable_entry* ent = (const ResTable_entry*)
                             (((const uint8_t*)type) + entriesStart + thisOffset);
                         if (((entriesStart + thisOffset)&0x3) != 0) {
-                            printf("NON-INTEGER ResTable_entry OFFSET: %p\n",
-                                 (void*)(entriesStart + thisOffset));
+                            printf("NON-INTEGER ResTable_entry OFFSET: 0x%x\n",
+                                 (entriesStart + thisOffset));
                             continue;
                         }
                         
-                        uint16_t esize = dtohs(ent->size);
+                        uintptr_t esize = dtohs(ent->size);
                         if ((esize&0x3) != 0) {
-                            printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize);
+                            printf("NON-INTEGER ResTable_entry SIZE: 0x%x\n", esize);
                             continue;
                         }
                         if ((thisOffset+esize) > typeSize) {
-                            printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n",
-                                   (void*)entriesStart, (void*)thisOffset,
-                                   (void*)esize, (void*)typeSize);
+                            printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+0x%x (size is 0x%x)\n",
+                                   entriesStart, thisOffset, esize, typeSize);
                             continue;
                         }
                             
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 3c55375..977ba80 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -5,7 +5,8 @@
 # Build the unit tests.
 test_src_files := \
     ObbFile_test.cpp \
-    ZipUtils_test.cpp
+    ZipUtils_test.cpp \
+    ResourceTypes_test.cpp
 
 shared_libraries := \
     libandroidfw \
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ResourceTypes_test.cpp
new file mode 100644
index 0000000..4888b4a
--- /dev/null
+++ b/libs/androidfw/tests/ResourceTypes_test.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2014 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 <androidfw/ResourceTypes.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+namespace android {
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
+     ResTable_config config;
+     config.packLanguage("en");
+
+     EXPECT_EQ('e', config.language[0]);
+     EXPECT_EQ('n', config.language[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackLanguage(out);
+     EXPECT_EQ('e', out[0]);
+     EXPECT_EQ('n', out[1]);
+     EXPECT_EQ(0, out[2]);
+     EXPECT_EQ(0, out[3]);
+
+     memset(out, 1, sizeof(out));
+     config.locale = 0;
+     config.unpackLanguage(out);
+     EXPECT_EQ(0, out[0]);
+     EXPECT_EQ(0, out[1]);
+     EXPECT_EQ(0, out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
+     ResTable_config config;
+     config.packRegion("US");
+
+     EXPECT_EQ('U', config.country[0]);
+     EXPECT_EQ('S', config.country[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackRegion(out);
+     EXPECT_EQ('U', out[0]);
+     EXPECT_EQ('S', out[1]);
+     EXPECT_EQ(0, out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
+     ResTable_config config;
+     config.packLanguage("eng");
+
+     // 1-00110-01 101-00100
+     EXPECT_EQ(0x99, config.language[0]);
+     EXPECT_EQ(0xa4, config.language[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackLanguage(out);
+     EXPECT_EQ('e', out[0]);
+     EXPECT_EQ('n', out[1]);
+     EXPECT_EQ('g', out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
+     ResTable_config config;
+     config.packRegion("419");
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackRegion(out);
+
+     EXPECT_EQ('4', out[0]);
+     EXPECT_EQ('1', out[1]);
+     EXPECT_EQ('9', out[2]);
+}
+
+/* static */ void fillIn(const char* lang, const char* country,
+        const char* script, const char* variant, ResTable_config* out) {
+     memset(out, 0, sizeof(ResTable_config));
+     if (lang != NULL) {
+         out->packLanguage(lang);
+     }
+
+     if (country != NULL) {
+         out->packRegion(country);
+     }
+
+     if (script != NULL) {
+         memcpy(out->localeScript, script, 4);
+     }
+
+     if (variant != NULL) {
+         memcpy(out->localeVariant, variant, strlen(variant));
+     }
+}
+
+TEST(ResourceTypesTest, IsMoreSpecificThan) {
+    ResTable_config l;
+    ResTable_config r;
+
+    fillIn("en", NULL, NULL, NULL, &l);
+    fillIn(NULL, NULL, NULL, NULL, &r);
+
+    EXPECT_TRUE(l.isMoreSpecificThan(r));
+    EXPECT_FALSE(r.isMoreSpecificThan(l));
+
+    fillIn("eng", NULL, NULL, NULL, &l);
+    EXPECT_TRUE(l.isMoreSpecificThan(r));
+    EXPECT_FALSE(r.isMoreSpecificThan(l));
+
+    fillIn("eng", "419", NULL, NULL, &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", NULL, NULL, NULL, &l);
+    fillIn("en", "US", NULL, NULL, &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", "US", NULL, NULL, &l);
+    fillIn("en", "US", "Latn", NULL, &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", "US", NULL, NULL, &l);
+    fillIn("en", "US", NULL, "POSIX", &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", "US", "Latn", NULL, &l);
+    fillIn("en", "US", NULL, "POSIX", &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+}
+
+TEST(ResourceTypesTest, setLocale) {
+    ResTable_config test;
+    test.setBcp47Locale("en-US");
+    EXPECT_EQ('e', test.language[0]);
+    EXPECT_EQ('n', test.language[1]);
+    EXPECT_EQ('U', test.country[0]);
+    EXPECT_EQ('S', test.country[1]);
+    EXPECT_EQ(0, test.localeScript[0]);
+    EXPECT_EQ(0, test.localeVariant[0]);
+
+    test.setBcp47Locale("eng-419");
+    char out[4] = { 1, 1, 1, 1};
+    test.unpackLanguage(out);
+    EXPECT_EQ('e', out[0]);
+    EXPECT_EQ('n', out[1]);
+    EXPECT_EQ('g', out[2]);
+    EXPECT_EQ(0, out[3]);
+    memset(out, 1, 4);
+    test.unpackRegion(out);
+    EXPECT_EQ('4', out[0]);
+    EXPECT_EQ('1', out[1]);
+    EXPECT_EQ('9', out[2]);
+
+
+    test.setBcp47Locale("en-Latn-419");
+    memset(out, 1, 4);
+    EXPECT_EQ('e', test.language[0]);
+    EXPECT_EQ('n', test.language[1]);
+
+    EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
+    test.unpackRegion(out);
+    EXPECT_EQ('4', out[0]);
+    EXPECT_EQ('1', out[1]);
+    EXPECT_EQ('9', out[2]);
+}
+
+}  // namespace android.
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index eb8bb9f..e8c3d3c 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -28,7 +28,7 @@
 // Lifecycle
 ///////////////////////////////////////////////////////////////////////////////
 
-void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) {
+void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
     if (mImage) {
         return;
     }
@@ -108,14 +108,19 @@
 /**
  * TODO: This method does not take the rotation flag into account
  */
-void AssetAtlas::createEntries(Caches& caches, int* map, int count) {
+void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
     const float width = float(mTexture->width);
     const float height = float(mTexture->height);
 
     for (int i = 0; i < count; ) {
-        SkBitmap* bitmap = (SkBitmap*) map[i++];
-        int x = map[i++];
-        int y = map[i++];
+        SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]);
+        // NOTE: We're converting from 64 bit signed values to 32 bit
+        // signed values. This is guaranteed to be safe because the "x"
+        // and "y" coordinate values are guaranteed to be representable
+        // with 32 bits. The array is 64 bits wide so that it can carry
+        // pointers on 64 bit architectures.
+        const int x = static_cast<int>(map[i++]);
+        const int y = static_cast<int>(map[i++]);
         bool rotated = map[i++] > 0;
 
         // Bitmaps should never be null, we're just extra paranoid
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index a28efc6..163bdbc 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -121,7 +121,7 @@
      * initialized. To re-initialize the atlas, you must
      * first call terminate().
      */
-    ANDROID_API void init(sp<GraphicBuffer> buffer, int* map, int count);
+    ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
 
     /**
      * Destroys the atlas texture. This object can be
@@ -176,7 +176,7 @@
     }
 
 private:
-    void createEntries(Caches& caches, int* map, int count);
+    void createEntries(Caches& caches, int64_t* map, int count);
 
     Texture* mTexture;
     Image* mImage;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 326805a..842e028 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1444,7 +1444,7 @@
                 DeferredDisplayList::kOpBatch_Text :
                 DeferredDisplayList::kOpBatch_ColorText;
 
-        deferInfo.mergeId = (mergeid_t)mPaint->getColor();
+        deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
 
         // don't merge decorated text - the decorations won't draw in order
         bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index dc0d98c..8a44604 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -129,7 +129,11 @@
         Mutex::Autolock _l(mLock);
         size_t count = mGarbage.size();
         for (size_t i = 0; i < count; i++) {
-            remove(patchesToRemove, mGarbage[i]);
+            Res_png_9patch* patch = mGarbage[i];
+            remove(patchesToRemove, patch);
+            // A Res_png_9patch is actually an array of byte that's larger
+            // than sizeof(Res_png_9patch). It must be freed as an array.
+            delete[] (int8_t*) patch;
         }
         mGarbage.clear();
     }
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 5df6408..cf8adf8 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -395,7 +395,9 @@
         Mutex::Autolock l(mLock);
         size_t count = mGarbage.size();
         for (size_t i = 0; i < count; i++) {
-            remove(pathsToRemove, mGarbage.itemAt(i));
+            const path_pair_t& pair = mGarbage.itemAt(i);
+            remove(pathsToRemove, pair);
+            delete pair.getFirst();
         }
         mGarbage.clear();
     }
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index 36e89c6..5b642b9 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -151,7 +151,7 @@
     mCaches.bindPixelBuffer(mBuffer);
     unmap();
     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
-            GL_UNSIGNED_BYTE, (void*) offset);
+            GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 3f77021..d276a29 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -213,8 +213,9 @@
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().pathCache.removeDeferred(resource);
+        } else {
+            delete resource;
         }
-        delete resource;
         return;
     }
     ref->destroyed = true;
@@ -235,8 +236,9 @@
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().textureCache.removeDeferred(resource);
+        } else {
+            delete resource;
         }
-        delete resource;
         return;
     }
     ref->destroyed = true;
@@ -292,13 +294,14 @@
     ssize_t index = mCache->indexOfKey(resource);
     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
+        // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().patchCache.removeDeferred(resource);
+        } else {
+            // A Res_png_9patch is actually an array of byte that's larger
+            // than sizeof(Res_png_9patch). It must be freed as an array.
+            delete[] (int8_t*) resource;
         }
-        // If we're not tracking this resource, just delete it
-        // A Res_png_9patch is actually an array of byte that's larger
-        // than sizeof(Res_png_9patch). It must be freed as an array.
-        delete[] (int8_t*) resource;
         return;
     }
     ref->destroyed = true;
@@ -355,16 +358,18 @@
                 SkBitmap* bitmap = (SkBitmap*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().textureCache.removeDeferred(bitmap);
+                } else {
+                    delete bitmap;
                 }
-                delete bitmap;
             }
             break;
             case kPath: {
                 SkPath* path = (SkPath*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().pathCache.removeDeferred(path);
+                } else {
+                    delete path;
                 }
-                delete path;
             }
             break;
             case kShader: {
@@ -380,11 +385,12 @@
             case kNinePatch: {
                 if (Caches::hasInstance()) {
                     Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
+                } else {
+                    // A Res_png_9patch is actually an array of byte that's larger
+                    // than sizeof(Res_png_9patch). It must be freed as an array.
+                    int8_t* patch = (int8_t*) resource;
+                    delete[] patch;
                 }
-                // A Res_png_9patch is actually an array of byte that's larger
-                // than sizeof(Res_png_9patch). It must be freed as an array.
-                int8_t* patch = (int8_t*) resource;
-                delete[] patch;
             }
             break;
             case kLayer: {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index ed0a79a..54a206b 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -184,7 +184,9 @@
     Mutex::Autolock _l(mLock);
     size_t count = mGarbage.size();
     for (size_t i = 0; i < count; i++) {
-        mCache.remove(mGarbage.itemAt(i));
+        const SkBitmap* bitmap = mGarbage.itemAt(i);
+        mCache.remove(bitmap);
+        delete bitmap;
     }
     mGarbage.clear();
 }
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 18983d8..8f5beb8 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -404,10 +404,10 @@
         // If it's still not valid, we couldn't cache it, so we shouldn't
         // draw garbage; also skip empty glyphs (spaces)
         if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) {
-            float penX = x + positions[(glyphsCount << 1)];
-            float penY = y + positions[(glyphsCount << 1) + 1];
+            int penX = x + (int) roundf(positions[(glyphsCount << 1)]);
+            int penY = y + (int) roundf(positions[(glyphsCount << 1) + 1]);
 
-            (*this.*render)(cachedGlyph, roundf(penX), roundf(penY),
+            (*this.*render)(cachedGlyph, penX, penY,
                     bitmap, bitmapW, bitmapH, bounds, positions);
         }
 
diff --git a/libs/hwui/utils/TinyHashMap.h b/libs/hwui/utils/TinyHashMap.h
index 8855140..4ff9a42 100644
--- a/libs/hwui/utils/TinyHashMap.h
+++ b/libs/hwui/utils/TinyHashMap.h
@@ -24,8 +24,6 @@
 
 /**
  * A very simple hash map that doesn't allow duplicate keys, overwriting the older entry.
- *
- * Currently, expects simple keys that are handled by hash_t()
  */
 template <typename TKey, typename TValue>
 class TinyHashMap {
@@ -36,7 +34,7 @@
      * Puts an entry in the hash, removing any existing entry with the same key
      */
     void put(TKey key, TValue value) {
-        hash_t hash = hash_t(key);
+        hash_t hash = android::hash_type(key);
 
         ssize_t index = mTable.find(-1, hash, key);
         if (index != -1) {
@@ -51,7 +49,7 @@
      * Return true if key is in the map, in which case stores the value in the output ref
      */
     bool get(TKey key, TValue& outValue) {
-        hash_t hash = hash_t(key);
+        hash_t hash = android::hash_type(key);
         ssize_t index = mTable.find(-1, hash, key);
         if (index == -1) {
             return false;
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 0030dbd..d475eee 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -707,6 +707,7 @@
     }
     status_t res = consumer->lockNextBuffer(buffer);
     if (res != NO_ERROR) {
+        ctx->returnLockedBuffer(buffer);
         if (res != BAD_VALUE /*no buffers*/) {
             if (res == NOT_ENOUGH_DATA) {
                 return ACQUIRE_MAX_IMAGES;
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 2c16a05..3561b06 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -132,7 +132,7 @@
 }
 
 // Constructor counterpart.
-static jint android_media_MediaMuxer_native_setup(
+static jlong android_media_MediaMuxer_native_setup(
         JNIEnv *env, jclass clazz, jobject fileDescriptor,
         jint format) {
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -142,7 +142,7 @@
         static_cast<MediaMuxer::OutputFormat>(format);
     sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);
     muxer->incStrong(clazz);
-    return int(muxer.get());
+    return reinterpret_cast<jlong>(muxer.get());
 }
 
 static void android_media_MediaMuxer_setOrientationHint(
diff --git a/native/android/asset_manager.cpp b/native/android/asset_manager.cpp
index 01db1d3..dee3f8c 100644
--- a/native/android/asset_manager.cpp
+++ b/native/android/asset_manager.cpp
@@ -76,12 +76,12 @@
 
         if (gJNIConfigured == false) {
             jclass amClass = env->FindClass("android/content/res/AssetManager");
-            gAssetManagerOffsets.mObject = env->GetFieldID(amClass, "mObject", "I");
+            gAssetManagerOffsets.mObject = env->GetFieldID(amClass, "mObject", "J");
             gJNIConfigured = true;
         }
     }
 
-    return (AAssetManager*) env->GetIntField(assetManager, gAssetManagerOffsets.mObject);
+    return (AAssetManager*) env->GetLongField(assetManager, gAssetManagerOffsets.mObject);
 }
 
 AAsset* AAssetManager_open(AAssetManager* amgr, const char* filename, int mode)
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index b93557d..cf09c58 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -160,6 +160,13 @@
         int display_id
     );
 
+    /**
+     * {@hide}
+     */
+    public static native EGLDisplay eglGetDisplay(
+        long display_id
+    );
+
     // C function EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor )
 
     public static native boolean eglInitialize(
@@ -324,7 +331,7 @@
     );
 
     // C function EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list )
-
+    // TODO Deprecate the below method
     public static native EGLSurface eglCreatePbufferFromClientBuffer(
         EGLDisplay dpy,
         int buftype,
@@ -333,6 +340,18 @@
         int[] attrib_list,
         int offset
     );
+    // TODO Unhide the below method
+    /**
+     * {@hide}
+     */
+    public static native EGLSurface eglCreatePbufferFromClientBuffer(
+        EGLDisplay dpy,
+        int buftype,
+        long buffer,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
 
     // C function EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value )
 
diff --git a/opengl/java/android/opengl/EGLConfig.java b/opengl/java/android/opengl/EGLConfig.java
index a7a6bbb..9881070 100644
--- a/opengl/java/android/opengl/EGLConfig.java
+++ b/opengl/java/android/opengl/EGLConfig.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLConfig extends EGLObjectHandle {
-    private EGLConfig(int handle) {
+    private EGLConfig(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLConfig)) return false;
 
         EGLConfig that = (EGLConfig) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLContext.java b/opengl/java/android/opengl/EGLContext.java
index c93bd6e..f791e7e 100644
--- a/opengl/java/android/opengl/EGLContext.java
+++ b/opengl/java/android/opengl/EGLContext.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLContext extends EGLObjectHandle {
-    private EGLContext(int handle) {
+    private EGLContext(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLContext)) return false;
 
         EGLContext that = (EGLContext) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLDisplay.java b/opengl/java/android/opengl/EGLDisplay.java
index 5b8043a..e872761 100644
--- a/opengl/java/android/opengl/EGLDisplay.java
+++ b/opengl/java/android/opengl/EGLDisplay.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLDisplay extends EGLObjectHandle {
-    private EGLDisplay(int handle) {
+    private EGLDisplay(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLDisplay)) return false;
 
         EGLDisplay that = (EGLDisplay) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLObjectHandle.java b/opengl/java/android/opengl/EGLObjectHandle.java
index d2710de..e6e3976 100644
--- a/opengl/java/android/opengl/EGLObjectHandle.java
+++ b/opengl/java/android/opengl/EGLObjectHandle.java
@@ -22,12 +22,20 @@
  *
  */
 public abstract class EGLObjectHandle {
-    private final int mHandle;
+    private final long mHandle;
 
+    // TODO Deprecate EGLObjectHandle(int) method
     protected EGLObjectHandle(int handle) {
         mHandle = handle;
     }
-
+    // TODO Unhide the EGLObjectHandle(long) method
+    /**
+     * {@hide}
+     */
+    protected EGLObjectHandle(long handle) {
+        mHandle = handle;
+    }
+    // TODO Deprecate getHandle() method in favor of getNativeHandle()
     /**
      * Returns the native handle of the wrapped EGL object. This handle can be
      * cast to the corresponding native type on the native side.
@@ -37,11 +45,27 @@
      * @return the native handle of the wrapped EGL object.
      */
     public int getHandle() {
-        return mHandle;
+        if ((mHandle & 0xffffffffL) != mHandle) {
+            throw new UnsupportedOperationException();
+        }
+        return (int)mHandle;
     }
 
+    // TODO Unhide getNativeHandle() method
+    /**
+     * {@hide}
+     */
+    public long getNativeHandle() {
+        return mHandle;
+    }
     @Override
     public int hashCode() {
-        return getHandle();
+        /*
+         * Based on the algorithm suggested in
+         * http://developer.android.com/reference/java/lang/Object.html
+         */
+        int result = 17;
+        result = 31 * result + (int) (mHandle ^ (mHandle >>> 32));
+        return result;
     }
 }
diff --git a/opengl/java/android/opengl/EGLSurface.java b/opengl/java/android/opengl/EGLSurface.java
index c379dc9..c200f72 100644
--- a/opengl/java/android/opengl/EGLSurface.java
+++ b/opengl/java/android/opengl/EGLSurface.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLSurface extends EGLObjectHandle {
-    private EGLSurface(int handle) {
+    private EGLSurface(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLSurface)) return false;
 
         EGLSurface that = (EGLSurface) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
index c2f4400..1902a40 100644
--- a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
@@ -19,13 +19,13 @@
 import javax.microedition.khronos.egl.*;
 
 public class EGLConfigImpl extends EGLConfig {
-    private int mEGLConfig;
+    private long mEGLConfig;
 
-    EGLConfigImpl(int config) {
+    EGLConfigImpl(long config) {
         mEGLConfig = config;
     }
     
-    int get() {
+    long get() {
         return mEGLConfig;
     }
 }
diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
index cd36099..47369ac 100644
--- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
@@ -21,13 +21,13 @@
 
 public class EGLContextImpl extends EGLContext {
     private GLImpl mGLContext;
-    int mEGLContext;
-    
-    public EGLContextImpl(int ctx) {
+    long mEGLContext;
+
+    public EGLContextImpl(long ctx) {
         mEGLContext = ctx;
         mGLContext = new GLImpl();
     }
- 
+
     @Override
     public GL getGL() {
         return mGLContext;
@@ -45,6 +45,12 @@
 
     @Override
     public int hashCode() {
-        return mEGLContext;
+        /*
+         * Based on the algorithm suggested in
+         * http://developer.android.com/reference/java/lang/Object.html
+         */
+        int result = 17;
+        result = 31 * result + (int) (mEGLContext ^ (mEGLContext >>> 32));
+        return result;
     }
 }
diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
index e6c9817..9b932fc 100644
--- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
@@ -19,9 +19,9 @@
 import javax.microedition.khronos.egl.*;
 
 public class EGLDisplayImpl extends EGLDisplay {
-    int mEGLDisplay;
+    long mEGLDisplay;
 
-    public EGLDisplayImpl(int dpy) {
+    public EGLDisplayImpl(long dpy) {
         mEGLDisplay = dpy;
     }
 
@@ -38,6 +38,12 @@
 
     @Override
     public int hashCode() {
-        return mEGLDisplay;
+        /*
+         * Based on the algorithm suggested in
+         * http://developer.android.com/reference/java/lang/Object.html
+         */
+        int result = 17;
+        result = 31 * result + (int) (mEGLDisplay ^ (mEGLDisplay >>> 32));
+        return result;
     }
 }
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 64a54c2..41fb072 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -51,7 +51,7 @@
     public static native int  getInitCount(EGLDisplay display);
 
     public EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list) {
-        int eglContextId = _eglCreateContext(display, config, share_context, attrib_list);
+        long eglContextId = _eglCreateContext(display, config, share_context, attrib_list);
         if (eglContextId == 0) {
             return EGL10.EGL_NO_CONTEXT;
         }
@@ -59,7 +59,7 @@
     }
 
     public EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list) {
-        int eglSurfaceId = _eglCreatePbufferSurface(display, config, attrib_list);
+        long eglSurfaceId = _eglCreatePbufferSurface(display, config, attrib_list);
         if (eglSurfaceId == 0) {
             return EGL10.EGL_NO_SURFACE;
         }
@@ -87,7 +87,7 @@
             sur = (Surface) native_window;
         }
 
-        int eglSurfaceId;
+        long eglSurfaceId;
         if (sur != null) {
             eglSurfaceId = _eglCreateWindowSurface(display, config, sur, attrib_list);
         } else if (native_window instanceof SurfaceTexture) {
@@ -106,7 +106,7 @@
     }
 
     public synchronized EGLDisplay eglGetDisplay(Object native_display) {
-        int value = _eglGetDisplay(native_display);
+        long value = _eglGetDisplay(native_display);
         if (value == 0) {
             return EGL10.EGL_NO_DISPLAY;
         }
@@ -116,7 +116,7 @@
     }
 
     public synchronized EGLContext eglGetCurrentContext() {
-        int value = _eglGetCurrentContext();
+        long value = _eglGetCurrentContext();
         if (value == 0) {
             return EGL10.EGL_NO_CONTEXT;
         }
@@ -126,7 +126,7 @@
     }
 
     public synchronized EGLDisplay eglGetCurrentDisplay() {
-        int value = _eglGetCurrentDisplay();
+        long value = _eglGetCurrentDisplay();
         if (value == 0) {
             return EGL10.EGL_NO_DISPLAY;
         }
@@ -136,7 +136,7 @@
     }
 
     public synchronized EGLSurface eglGetCurrentSurface(int readdraw) {
-        int value = _eglGetCurrentSurface(readdraw);
+        long value = _eglGetCurrentSurface(readdraw);
         if (value == 0) {
             return EGL10.EGL_NO_SURFACE;
         }
@@ -145,15 +145,15 @@
         return mSurface;
     }
 
-    private native int _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
-    private native int _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
+    private native long _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
+    private native long _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
     private native void _eglCreatePixmapSurface(EGLSurface sur, EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list);
-    private native int _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
-    private native int _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
-    private native int _eglGetDisplay(Object native_display);
-    private native int _eglGetCurrentContext();
-    private native int _eglGetCurrentDisplay();
-    private native int _eglGetCurrentSurface(int readdraw);
+    private native long _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+    private native long _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+    private native long _eglGetDisplay(Object native_display);
+    private native long _eglGetCurrentContext();
+    private native long _eglGetCurrentDisplay();
+    private native long _eglGetCurrentSurface(int readdraw);
 
     native private static void _nativeClassInit();
     static { _nativeClassInit(); }
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index e7f15dc..7a3ed24 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -19,13 +19,13 @@
 import javax.microedition.khronos.egl.*;
 
 public class EGLSurfaceImpl extends EGLSurface {
-    int mEGLSurface;
-    private int mNativePixelRef;
+    long mEGLSurface;
+    private long mNativePixelRef;
     public EGLSurfaceImpl() {
         mEGLSurface = 0;
         mNativePixelRef = 0;
     }
-    public EGLSurfaceImpl(int surface) {
+    public EGLSurfaceImpl(long surface) {
         mEGLSurface = surface;
         mNativePixelRef = 0;
     }
@@ -43,6 +43,12 @@
 
     @Override
     public int hashCode() {
-        return mEGLSurface;
+        /*
+         * Based on the algorithm suggested in
+         * http://developer.android.com/reference/java/lang/Object.html
+         */
+        int result = 17;
+        result = 31 * result + (int) (mEGLSurface ^ (mEGLSurface >>> 32));
+        return result;
     }
 }
diff --git a/preloaded-classes b/preloaded-classes
index 342126d..02bd0bc 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -2456,8 +2456,6 @@
 org.apache.harmony.security.fortress.Engine$SpiAndProvider
 org.apache.harmony.security.fortress.SecurityAccess
 org.apache.harmony.security.fortress.Services
-org.apache.harmony.security.provider.cert.DRLCertFactory
-org.apache.harmony.security.provider.cert.X509CertImpl
 org.apache.harmony.security.provider.crypto.CryptoProvider
 org.apache.harmony.security.utils.AlgNameMapper
 org.apache.harmony.security.utils.ObjectIdentifier
diff --git a/graphics/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
similarity index 85%
rename from graphics/java/android/renderscript/Allocation.java
rename to rs/java/android/renderscript/Allocation.java
index dca934f..c2bab91 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -24,7 +24,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.view.Surface;
-import android.graphics.SurfaceTexture;
 import android.util.Log;
 import android.util.TypedValue;
 import android.graphics.Canvas;
@@ -78,10 +77,69 @@
     int mCurrentDimY;
     int mCurrentDimZ;
     int mCurrentCount;
-    static HashMap<Integer, Allocation> mAllocationMap =
-            new HashMap<Integer, Allocation>();
+    static HashMap<Long, Allocation> mAllocationMap =
+            new HashMap<Long, Allocation>();
     OnBufferAvailableListener mBufferNotifier;
 
+    private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
+        final Class c = d.getClass();
+        if (!c.isArray()) {
+            throw new RSIllegalArgumentException("Object passed is not an array of primitives.");
+        }
+        final Class cmp = c.getComponentType();
+        if (!cmp.isPrimitive()) {
+            throw new RSIllegalArgumentException("Object passed is not an Array of primitives.");
+        }
+
+        if (cmp == Long.TYPE) {
+            if (checkType) {
+                validateIsInt64();
+                return mType.mElement.mType;
+            }
+            return Element.DataType.SIGNED_64;
+        }
+
+        if (cmp == Integer.TYPE) {
+            if (checkType) {
+                validateIsInt32();
+                return mType.mElement.mType;
+            }
+            return Element.DataType.SIGNED_32;
+        }
+
+        if (cmp == Short.TYPE) {
+            if (checkType) {
+                validateIsInt16();
+                return mType.mElement.mType;
+            }
+            return Element.DataType.SIGNED_16;
+        }
+
+        if (cmp == Byte.TYPE) {
+            if (checkType) {
+                validateIsInt8();
+                return mType.mElement.mType;
+            }
+            return Element.DataType.SIGNED_8;
+        }
+
+        if (cmp == Float.TYPE) {
+            if (checkType) {
+                validateIsFloat32();
+            }
+            return Element.DataType.FLOAT_32;
+        }
+
+        if (cmp == Double.TYPE) {
+            if (checkType) {
+                validateIsFloat64();
+            }
+            return Element.DataType.FLOAT_64;
+        }
+        return null;
+    }
+
+
     /**
      * The usage of the Allocation.  These signal to RenderScript where to place
      * the Allocation in memory.
@@ -127,17 +185,17 @@
     public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
 
     /**
-     * The Allocation will be used as a {@link android.graphics.SurfaceTexture}
-     * consumer.  This usage will cause the Allocation to be created as
-     * read-only.
+     * The Allocation will be used as a {@link android.view.Surface}
+     * consumer.  This usage will cause the Allocation to be created
+     * as read-only.
      *
      */
     public static final int USAGE_IO_INPUT = 0x0020;
 
     /**
-     * The Allocation will be used as a {@link android.graphics.SurfaceTexture}
+     * The Allocation will be used as a {@link android.view.Surface}
      * producer.  The dimensions and format of the {@link
-     * android.graphics.SurfaceTexture} will be forced to those of the
+     * android.view.Surface} will be forced to those of the
      * Allocation.
      *
      */
@@ -188,7 +246,7 @@
     }
 
 
-    private int getIDSafe() {
+    private long getIDSafe() {
         if (mAdaptedAllocation != null) {
             return mAdaptedAllocation.getID(mRS);
         }
@@ -224,6 +282,9 @@
      *
      */
     public int getBytesSize() {
+        if (mType.mDimYuv != 0) {
+            return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5);
+        }
         return mType.getCount() * mType.getElement().getBytesSize();
     }
 
@@ -244,7 +305,7 @@
         mBitmap = b;
     }
 
-    Allocation(int id, RenderScript rs, Type t, int usage) {
+    Allocation(long id, RenderScript rs, Type t, int usage) {
         super(id, rs);
         if ((usage & ~(USAGE_SCRIPT |
                        USAGE_GRAPHICS_TEXTURE |
@@ -290,6 +351,15 @@
         super.finalize();
     }
 
+    private void validateIsInt64() {
+        if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
+            (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "64 bit integer source does not match allocation type " + mType.mElement.mType);
+    }
+
     private void validateIsInt32() {
         if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
             (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
@@ -325,6 +395,14 @@
             "32 bit float source does not match allocation type " + mType.mElement.mType);
     }
 
+    private void validateIsFloat64() {
+        if (mType.mElement.mType == Element.DataType.FLOAT_64) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "64 bit float source does not match allocation type " + mType.mElement.mType);
+    }
+
     private void validateIsObject() {
         if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
             (mType.mElement.mType == Element.DataType.RS_TYPE) ||
@@ -345,7 +423,7 @@
     @Override
     void updateFromNative() {
         super.updateFromNative();
-        int typeID = mRS.nAllocationGetType(getID(mRS));
+        long typeID = mRS.nAllocationGetType(getID(mRS));
         if(typeID != 0) {
             mType = new Type(typeID, mRS);
             mType.updateFromNative();
@@ -412,14 +490,6 @@
     }
 
     /**
-     * Delete once code is updated.
-     * @hide
-     */
-    public void ioSendOutput() {
-        ioSend();
-    }
-
-    /**
      * Receive the latest input into the Allocation. This operation
      * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
      *
@@ -448,9 +518,11 @@
             throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
                                                  mCurrentCount + ", array length = " + d.length);
         }
+        // FIXME: requires 64-bit path
+
         int i[] = new int[d.length];
         for (int ct=0; ct < d.length; ct++) {
-            i[ct] = d[ct].getID(mRS);
+            i[ct] = (int)d[ct].getID(mRS);
         }
         copy1DRangeFromUnchecked(0, mCurrentCount, i);
         Trace.traceEnd(RenderScript.TRACE_TAG);
@@ -511,6 +583,34 @@
         }
     }
 
+    private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+        mRS.validate();
+        if (mCurrentDimZ > 0) {
+            copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
+        } else if (mCurrentDimY > 0) {
+            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
+        } else {
+            copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
+        }
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * Copy into this Allocation from an array. This method does not guarantee
+     * that the Allocation is compatible with the input buffer; it copies memory
+     * without reinterpretation.
+     *
+     * @param array The source data array
+     * @hide
+     */
+    public void copyFromUnchecked(Object array) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+        copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
+                          java.lang.reflect.Array.getLength(array));
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
     /**
      * Copy into this Allocation from an array. This method does not guarantee
      * that the Allocation is compatible with the input buffer; it copies memory
@@ -519,16 +619,7 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(int[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFromUnchecked(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -539,16 +630,7 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(short[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFromUnchecked(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -559,16 +641,7 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(byte[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFromUnchecked(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -579,37 +652,36 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(float[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFromUnchecked(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
     }
 
 
     /**
      * Copy into this Allocation from an array.  This variant is type checked
      * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} does not match the array's
+     * primitive type.
+     *
+     * @param d the source data array
+     * @hide
+     */
+    public void copyFrom(Object array) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+        copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
+                          java.lang.reflect.Array.getLength(array));
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * Copy into this Allocation from an array.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
      * android.renderscript.Element} is not a 32 bit integer type.
      *
      * @param d the source data array
      */
     public void copyFrom(int[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFrom(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        validateIsInt32();
+        copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -620,16 +692,8 @@
      * @param d the source data array
      */
     public void copyFrom(short[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFrom(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        validateIsInt16();
+        copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -640,16 +704,8 @@
      * @param d the source data array
      */
     public void copyFrom(byte[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFrom(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        validateIsInt8();
+        copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -660,16 +716,8 @@
      * @param d the source data array
      */
     public void copyFrom(float[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
-        } else {
-            copy1DRangeFrom(0, mCurrentCount, d);
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        validateIsFloat32();
+        copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
     }
 
     /**
@@ -798,6 +846,30 @@
         mRS.nAllocationGenerateMipmaps(getID(mRS));
     }
 
+    private void copy1DRangeFromUnchecked(int off, int count, Object array,
+                                          Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
+        final int dataSize = mType.mElement.getBytesSize() * count;
+        data1DChecks(off, count, arrayLen * dt.mSize, dataSize);
+        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * Copy an array into part of this Allocation.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param array The source data array
+     * @hide
+     */
+    public void copy1DRangeFromUnchecked(int off, int count, Object array) {
+        copy1DRangeFromUnchecked(off, count, array,
+                                 validateObjectIsPrimitiveArray(array, false),
+                                 java.lang.reflect.Array.getLength(array));
+    }
+
     /**
      * Copy an array into part of this Allocation.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
@@ -807,11 +879,7 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -823,11 +891,7 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 2, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -839,11 +903,7 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -855,11 +915,24 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
+    }
+
+
+    /**
+     * Copy an array into part of this Allocation.  This variant is type checked
+     * and will generate exceptions if the Allocation type does not
+     * match the component type of the array passed in.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param array The source data array.
+     * @hide
+     */
+    public void copy1DRangeFrom(int off, int count, Object array) {
+        copy1DRangeFromUnchecked(off, count, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
     }
 
     /**
@@ -872,10 +945,8 @@
      * @param d the source data array
      */
     public void copy1DRangeFrom(int off, int count, int[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
         validateIsInt32();
-        copy1DRangeFromUnchecked(off, count, d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -888,10 +959,8 @@
      * @param d the source data array
      */
     public void copy1DRangeFrom(int off, int count, short[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
         validateIsInt16();
-        copy1DRangeFromUnchecked(off, count, d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -904,10 +973,8 @@
      * @param d the source data array
      */
     public void copy1DRangeFrom(int off, int count, byte[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
         validateIsInt8();
-        copy1DRangeFromUnchecked(off, count, d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -920,11 +987,10 @@
      * @param d the source data array.
      */
     public void copy1DRangeFrom(int off, int count, float[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
         validateIsFloat32();
-        copy1DRangeFromUnchecked(off, count, d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
     }
+
      /**
      * Copy part of an Allocation into this Allocation.
      *
@@ -959,39 +1025,32 @@
         }
     }
 
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, byte[] data) {
+    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
+                                  Element.DataType dt, int arrayLen) {
         Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length);
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+                              array, arrayLen * dt.mSize, dt);
         Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 2);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
-    }
-
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 4);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
-    }
-
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 4);
+    /**
+     * Copy from an array into a rectangular region in this Allocation.  The
+     * array is assumed to be tightly packed.
+     *
+     * @param xoff X offset of the region to update in this Allocation
+     * @param yoff Y offset of the region to update in this Allocation
+     * @param w Width of the region to update
+     * @param h Height of the region to update
+     * @param data to be placed into the Allocation
+     * @hide
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
         Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
@@ -1006,10 +1065,9 @@
      * @param data to be placed into the Allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
         validateIsInt8();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_8, data.length);
     }
 
     /**
@@ -1023,10 +1081,9 @@
      * @param data to be placed into the Allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
         validateIsInt16();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_16, data.length);
     }
 
     /**
@@ -1040,10 +1097,9 @@
      * @param data to be placed into the Allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
         validateIsInt32();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_32, data.length);
     }
 
     /**
@@ -1057,10 +1113,9 @@
      * @param data to be placed into the Allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
         validateIsFloat32();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.FLOAT_32, data.length);
     }
 
     /**
@@ -1133,49 +1188,18 @@
      * @hide
      *
      */
-    void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) {
+    private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
+                                          Object array, Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
         mRS.validate();
         validate3DRange(xoff, yoff, zoff, w, h, d);
-        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
-                              w, h, d, data, data.length);
+        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+                              array, arrayLen * dt.mSize, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
      * @hide
-     *
-     */
-    void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) {
-        mRS.validate();
-        validate3DRange(xoff, yoff, zoff, w, h, d);
-        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
-                              w, h, d, data, data.length * 2);
-    }
-
-    /**
-     * @hide
-     *
-     */
-    void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) {
-        mRS.validate();
-        validate3DRange(xoff, yoff, zoff, w, h, d);
-        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
-                              w, h, d, data, data.length * 4);
-    }
-
-    /**
-     * @hide
-     *
-     */
-    void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) {
-        mRS.validate();
-        validate3DRange(xoff, yoff, zoff, w, h, d);
-        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
-                              w, h, d, data, data.length * 4);
-    }
-
-
-    /**
-     * @hide
      * Copy a rectangular region from the array into the allocation.
      * The array is assumed to be tightly packed.
      *
@@ -1187,36 +1211,12 @@
      * @param d Depth of the region to update
      * @param data to be placed into the allocation
      */
-    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) {
-        validateIsInt8();
-        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
-    }
-
-    /**
-     * @hide
-     *
-     */
-    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) {
-        validateIsInt16();
-        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
-    }
-
-    /**
-     * @hide
-     *
-     */
-    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) {
-        validateIsInt32();
-        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
-    }
-
-    /**
-     * @hide
-     *
-     */
-    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) {
-        validateIsFloat32();
-        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
+    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
+        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
+        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1260,6 +1260,27 @@
         Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
+    private void copyTo(Object array, Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+        mRS.validate();
+        mRS.nAllocationRead(getID(mRS), array, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * Copy from the Allocation into an array.  The array must be at
+     * least as large as the Allocation.  The
+     * {@link android.renderscript.Element} must match the component
+     * type of the array passed in.
+     *
+     * @param array The array to be set from the Allocation.
+     * @hide
+     */
+    public void copyTo(Object array) {
+        copyTo(array, validateObjectIsPrimitiveArray(array, true),
+               java.lang.reflect.Array.getLength(array));
+    }
+
     /**
      * Copy from the Allocation into a byte array.  The array must be at least
      * as large as the Allocation.  The allocation must be of an 8 bit integer
@@ -1268,11 +1289,8 @@
      * @param d The array to be set from the Allocation.
      */
     public void copyTo(byte[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
         validateIsInt8();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -1283,11 +1301,8 @@
      * @param d The array to be set from the Allocation.
      */
     public void copyTo(short[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
         validateIsInt16();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -1298,11 +1313,8 @@
      * @param d The array to be set from the Allocation.
      */
     public void copyTo(int[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
         validateIsInt32();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -1313,11 +1325,8 @@
      * @param d The array to be set from the Allocation.
      */
     public void copyTo(float[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
         validateIsFloat32();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.FLOAT_32, d.length);
     }
 
     /**
@@ -1342,7 +1351,7 @@
         mRS.nAllocationResize1D(getID(mRS), dimX);
         mRS.finish();  // Necessary because resize is fifoed and update is async.
 
-        int typeID = mRS.nAllocationGetType(getID(mRS));
+        long typeID = mRS.nAllocationGetType(getID(mRS));
         mType = new Type(typeID, mRS);
         mType.updateFromNative();
         updateCacheInfo(mType);
@@ -1372,7 +1381,7 @@
         if (type.getID(rs) == 0) {
             throw new RSInvalidStateException("Bad Type");
         }
-        int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+        long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
         if (id == 0) {
             throw new RSRuntimeException("Allocation creation failed.");
         }
@@ -1427,7 +1436,7 @@
         b.setX(count);
         Type t = b.create();
 
-        int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
+        long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
         if (id == 0) {
             throw new RSRuntimeException("Allocation creation failed.");
         }
@@ -1511,7 +1520,7 @@
         if (mips == MipmapControl.MIPMAP_NONE &&
             t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
             usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
-            int id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
+            long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
             if (id == 0) {
                 throw new RSRuntimeException("Load failed.");
             }
@@ -1523,7 +1532,7 @@
         }
 
 
-        int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
+        long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
         if (id == 0) {
             throw new RSRuntimeException("Load failed.");
         }
@@ -1547,13 +1556,6 @@
     }
 
     /**
-     * @hide
-     */
-    public void setSurfaceTexture(SurfaceTexture st) {
-        setSurface(new Surface(st));
-    }
-
-    /**
      * Associate a {@link android.view.Surface} with this Allocation. This
      * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
      *
@@ -1633,7 +1635,7 @@
         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
         Type t = tb.create();
 
-        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
+        long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
         if(id == 0) {
             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
         }
@@ -1858,14 +1860,14 @@
      */
     public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
         synchronized(mAllocationMap) {
-            mAllocationMap.put(new Integer(getID(mRS)), this);
+            mAllocationMap.put(new Long(getID(mRS)), this);
             mBufferNotifier = callback;
         }
     }
 
     static void sendBufferNotification(int id) {
         synchronized(mAllocationMap) {
-            Allocation a = mAllocationMap.get(new Integer(id));
+            Allocation a = mAllocationMap.get(new Long(id));
 
             if ((a != null) && (a.mBufferNotifier != null)) {
                 a.mBufferNotifier.onBufferAvailable(a);
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/rs/java/android/renderscript/AllocationAdapter.java
similarity index 97%
rename from graphics/java/android/renderscript/AllocationAdapter.java
rename to rs/java/android/renderscript/AllocationAdapter.java
index a6645bb..fd20cae 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/rs/java/android/renderscript/AllocationAdapter.java
@@ -26,12 +26,12 @@
  *
  **/
 public class AllocationAdapter extends Allocation {
-    AllocationAdapter(int id, RenderScript rs, Allocation alloc) {
+    AllocationAdapter(long id, RenderScript rs, Allocation alloc) {
         super(id, rs, alloc.mType, alloc.mUsage);
         mAdaptedAllocation = alloc;
     }
 
-    int getID(RenderScript rs) {
+    long getID(RenderScript rs) {
         throw new RSInvalidStateException(
             "This operation is not supported with adapters at this time.");
     }
@@ -224,7 +224,6 @@
     }
 
     static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
-        android.util.Log.e("rs", "create2d " + a);
         rs.validate();
         AllocationAdapter aa = new AllocationAdapter(0, rs, a);
         aa.mConstrainedLOD = true;
diff --git a/graphics/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
similarity index 82%
rename from graphics/java/android/renderscript/BaseObj.java
rename to rs/java/android/renderscript/BaseObj.java
index e17d79a..b386dd7 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -16,7 +16,7 @@
 
 package android.renderscript;
 
-import android.util.Log;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
  * BaseObj is the base class for all RenderScript objects owned by a RS context.
@@ -25,14 +25,14 @@
  *
  **/
 public class BaseObj {
-    BaseObj(int id, RenderScript rs) {
+    BaseObj(long id, RenderScript rs) {
         rs.validate();
         mRS = rs;
         mID = id;
         mDestroyed = false;
     }
 
-    void setID(int id) {
+    void setID(long id) {
         if (mID != 0) {
             throw new RSRuntimeException("Internal Error, reset of object ID.");
         }
@@ -46,9 +46,9 @@
      * @param rs Context to verify against internal context for
      *           match.
      *
-     * @return int
+     * @return long
      */
-    int getID(RenderScript rs) {
+    long getID(RenderScript rs) {
         mRS.validate();
         if (mDestroyed) {
             throw new RSInvalidStateException("using a destroyed object.");
@@ -68,7 +68,7 @@
         }
     }
 
-    private int mID;
+    private long mID;
     private boolean mDestroyed;
     private String mName;
     RenderScript mRS;
@@ -109,17 +109,31 @@
         return mName;
     }
 
-    protected void finalize() throws Throwable {
-        if (!mDestroyed) {
-            if(mID != 0 && mRS.isAlive()) {
+    private void helpDestroy() {
+        boolean shouldDestroy = false;
+        synchronized(this) {
+            if (!mDestroyed) {
+                shouldDestroy = true;
+                mDestroyed = true;
+            }
+        }
+
+        if (shouldDestroy) {
+            // must include nObjDestroy in the critical section
+            ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
+            rlock.lock();
+            // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy
+            if(mRS.isAlive() && mID != 0) {
                 mRS.nObjDestroy(mID);
             }
+            rlock.unlock();
             mRS = null;
             mID = 0;
-            mDestroyed = true;
-            //Log.v(RenderScript.LOG_TAG, getClass() +
-            // " auto finalizing object without having released the RS reference.");
         }
+    }
+
+    protected void finalize() throws Throwable {
+        helpDestroy();
         super.finalize();
     }
 
@@ -128,12 +142,11 @@
      * primary use is to force immediate cleanup of resources when it is
      * believed the GC will not respond quickly enough.
      */
-    synchronized public void destroy() {
+    public void destroy() {
         if(mDestroyed) {
             throw new RSInvalidStateException("Object already destroyed.");
         }
-        mDestroyed = true;
-        mRS.nObjDestroy(mID);
+        helpDestroy();
     }
 
     /**
@@ -152,7 +165,7 @@
      */
     @Override
     public int hashCode() {
-        return mID;
+        return (int)((mID & 0xfffffff) ^ (mID >> 32));
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Byte2.java b/rs/java/android/renderscript/Byte2.java
similarity index 100%
rename from graphics/java/android/renderscript/Byte2.java
rename to rs/java/android/renderscript/Byte2.java
diff --git a/graphics/java/android/renderscript/Byte3.java b/rs/java/android/renderscript/Byte3.java
similarity index 100%
rename from graphics/java/android/renderscript/Byte3.java
rename to rs/java/android/renderscript/Byte3.java
diff --git a/graphics/java/android/renderscript/Byte4.java b/rs/java/android/renderscript/Byte4.java
similarity index 100%
rename from graphics/java/android/renderscript/Byte4.java
rename to rs/java/android/renderscript/Byte4.java
diff --git a/graphics/java/android/renderscript/Double2.java b/rs/java/android/renderscript/Double2.java
similarity index 100%
rename from graphics/java/android/renderscript/Double2.java
rename to rs/java/android/renderscript/Double2.java
diff --git a/graphics/java/android/renderscript/Double3.java b/rs/java/android/renderscript/Double3.java
similarity index 100%
rename from graphics/java/android/renderscript/Double3.java
rename to rs/java/android/renderscript/Double3.java
diff --git a/graphics/java/android/renderscript/Double4.java b/rs/java/android/renderscript/Double4.java
similarity index 100%
rename from graphics/java/android/renderscript/Double4.java
rename to rs/java/android/renderscript/Double4.java
diff --git a/graphics/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
similarity index 98%
rename from graphics/java/android/renderscript/Element.java
rename to rs/java/android/renderscript/Element.java
index 68badfa..2932770 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -759,7 +759,7 @@
         return rs.mElement_MATRIX_2X2;
     }
 
-    Element(int id, RenderScript rs, Element[] e, String[] n, int[] as) {
+    Element(long id, RenderScript rs, Element[] e, String[] n, int[] as) {
         super(id, rs);
         mSize = 0;
         mVectorSize = 1;
@@ -776,7 +776,7 @@
         updateVisibleSubElements();
     }
 
-    Element(int id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
+    Element(long id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
         super(id, rs);
         if ((dt != DataType.UNSIGNED_5_6_5) &&
             (dt != DataType.UNSIGNED_4_4_4_4) &&
@@ -795,7 +795,7 @@
         mVectorSize = size;
     }
 
-    Element(int id, RenderScript rs) {
+    Element(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -803,6 +803,8 @@
     void updateFromNative() {
         super.updateFromNative();
 
+        // FIXME: updateFromNative is broken in JNI for 64-bit
+
         // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
         int[] dataBuffer = new int[5];
         mRS.nElementGetNativeData(getID(mRS), dataBuffer);
@@ -853,7 +855,7 @@
         DataKind dk = DataKind.USER;
         boolean norm = false;
         int vecSize = 1;
-        int id = rs.nElementCreate(dt.mID, dk.mID, norm, vecSize);
+        long id = rs.nElementCreate(dt.mID, dk.mID, norm, vecSize);
         return new Element(id, rs, dt, dk, norm, vecSize);
     }
 
@@ -890,7 +892,7 @@
         case BOOLEAN: {
             DataKind dk = DataKind.USER;
             boolean norm = false;
-            int id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
+            long id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
             return new Element(id, rs, dt, dk, norm, size);
         }
 
@@ -961,7 +963,7 @@
         }
 
         boolean norm = true;
-        int id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
+        long id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
         return new Element(id, rs, dt, dk, norm, size);
     }
 
@@ -1088,11 +1090,12 @@
             java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount);
             java.lang.System.arraycopy(mArraySizes, 0, asin, 0, mCount);
 
+            // FIXME: broken for 64-bit
             int[] ids = new int[ein.length];
             for (int ct = 0; ct < ein.length; ct++ ) {
-                ids[ct] = ein[ct].getID(mRS);
+                ids[ct] = (int)ein[ct].getID(mRS);
             }
-            int id = mRS.nElementCreate2(ids, sin, asin);
+            long id = mRS.nElementCreate2(ids, sin, asin);
             return new Element(id, mRS, ein, sin, asin);
         }
     }
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
similarity index 98%
rename from graphics/java/android/renderscript/FieldPacker.java
rename to rs/java/android/renderscript/FieldPacker.java
index fed97d6..cf20e63 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -232,7 +232,8 @@
 
     public void addObj(BaseObj obj) {
         if (obj != null) {
-            addI32(obj.getID(null));
+            // FIXME: this is fine for 32-bit but needs a path for 64-bit
+            addI32((int)obj.getID(null));
         } else {
             addI32(0);
         }
diff --git a/graphics/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
similarity index 94%
rename from graphics/java/android/renderscript/FileA3D.java
rename to rs/java/android/renderscript/FileA3D.java
index e41f02d..04bc7c6 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -80,7 +80,7 @@
     public static class IndexEntry {
         RenderScript mRS;
         int mIndex;
-        int mID;
+        long mID;
         String mName;
         EntryType mEntryType;
         BaseObj mLoadedObj;
@@ -141,7 +141,7 @@
                 return null;
             }
 
-            int objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
+            long objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
             if(objectID == 0) {
                 return null;
             }
@@ -156,7 +156,7 @@
             return entry.mLoadedObj;
         }
 
-        IndexEntry(RenderScript rs, int index, int id, String name, EntryType type) {
+        IndexEntry(RenderScript rs, int index, long id, String name, EntryType type) {
             mRS = rs;
             mIndex = index;
             mID = id;
@@ -169,7 +169,7 @@
     IndexEntry[] mFileEntries;
     InputStream mInputStream;
 
-    FileA3D(int id, RenderScript rs, InputStream stream) {
+    FileA3D(long id, RenderScript rs, InputStream stream) {
         super(id, rs);
         mInputStream = stream;
     }
@@ -232,7 +232,7 @@
     */
     static public FileA3D createFromAsset(RenderScript rs, AssetManager mgr, String path) {
         rs.validate();
-        int fileId = rs.nFileA3DCreateFromAsset(mgr, path);
+        long fileId = rs.nFileA3DCreateFromAsset(mgr, path);
 
         if(fileId == 0) {
             throw new RSRuntimeException("Unable to create a3d file from asset " + path);
@@ -252,7 +252,7 @@
     * @return a3d file containing renderscript objects
     */
     static public FileA3D createFromFile(RenderScript rs, String path) {
-        int fileId = rs.nFileA3DCreateFromFile(path);
+        long fileId = rs.nFileA3DCreateFromFile(path);
 
         if(fileId == 0) {
             throw new RSRuntimeException("Unable to create a3d file from " + path);
@@ -295,9 +295,9 @@
             throw new RSRuntimeException("Unable to open resource " + id);
         }
 
-        int fileId = 0;
+        long fileId = 0;
         if (is instanceof AssetManager.AssetInputStream) {
-            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
             fileId = rs.nFileA3DCreateFromAssetStream(asset);
         } else {
             throw new RSRuntimeException("Unsupported asset stream");
diff --git a/graphics/java/android/renderscript/Float2.java b/rs/java/android/renderscript/Float2.java
similarity index 100%
rename from graphics/java/android/renderscript/Float2.java
rename to rs/java/android/renderscript/Float2.java
diff --git a/graphics/java/android/renderscript/Float3.java b/rs/java/android/renderscript/Float3.java
similarity index 100%
rename from graphics/java/android/renderscript/Float3.java
rename to rs/java/android/renderscript/Float3.java
diff --git a/graphics/java/android/renderscript/Float4.java b/rs/java/android/renderscript/Float4.java
similarity index 100%
rename from graphics/java/android/renderscript/Float4.java
rename to rs/java/android/renderscript/Float4.java
diff --git a/graphics/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
similarity index 96%
rename from graphics/java/android/renderscript/Font.java
rename to rs/java/android/renderscript/Font.java
index 0375d2b..cfd11c0 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -151,7 +151,7 @@
         return "DroidSans.ttf";
     }
 
-    Font(int id, RenderScript rs) {
+    Font(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -162,7 +162,7 @@
     static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize) {
         rs.validate();
         int dpi = res.getDisplayMetrics().densityDpi;
-        int fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
+        long fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
 
         if(fontId == 0) {
             throw new RSRuntimeException("Unable to create font from file " + path);
@@ -187,7 +187,7 @@
         AssetManager mgr = res.getAssets();
         int dpi = res.getDisplayMetrics().densityDpi;
 
-        int fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
+        long fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
         if(fontId == 0) {
             throw new RSRuntimeException("Unable to create font from asset " + path);
         }
@@ -211,9 +211,9 @@
 
         int dpi = res.getDisplayMetrics().densityDpi;
 
-        int fontId = 0;
+        long fontId = 0;
         if (is instanceof AssetManager.AssetInputStream) {
-            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
             fontId = rs.nFontCreateFromAssetStream(name, pointSize, dpi, asset);
         } else {
             throw new RSRuntimeException("Unsupported asset stream created");
diff --git a/graphics/java/android/renderscript/Int2.java b/rs/java/android/renderscript/Int2.java
similarity index 100%
rename from graphics/java/android/renderscript/Int2.java
rename to rs/java/android/renderscript/Int2.java
diff --git a/graphics/java/android/renderscript/Int3.java b/rs/java/android/renderscript/Int3.java
similarity index 100%
rename from graphics/java/android/renderscript/Int3.java
rename to rs/java/android/renderscript/Int3.java
diff --git a/graphics/java/android/renderscript/Int4.java b/rs/java/android/renderscript/Int4.java
similarity index 100%
rename from graphics/java/android/renderscript/Int4.java
rename to rs/java/android/renderscript/Int4.java
diff --git a/graphics/java/android/renderscript/Long2.java b/rs/java/android/renderscript/Long2.java
similarity index 100%
rename from graphics/java/android/renderscript/Long2.java
rename to rs/java/android/renderscript/Long2.java
diff --git a/graphics/java/android/renderscript/Long3.java b/rs/java/android/renderscript/Long3.java
similarity index 100%
rename from graphics/java/android/renderscript/Long3.java
rename to rs/java/android/renderscript/Long3.java
diff --git a/graphics/java/android/renderscript/Long4.java b/rs/java/android/renderscript/Long4.java
similarity index 99%
rename from graphics/java/android/renderscript/Long4.java
rename to rs/java/android/renderscript/Long4.java
index 757b910..1a1ad74 100644
--- a/graphics/java/android/renderscript/Long4.java
+++ b/rs/java/android/renderscript/Long4.java
@@ -505,7 +505,7 @@
      * @param data
      * @param offset
      */
-    public void copyTo(Long[] data, int offset) {
+    public void copyTo(long[] data, int offset) {
         data[offset] = (long)(x);
         data[offset + 1] = (long)(y);
         data[offset + 2] = (long)(z);
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/rs/java/android/renderscript/Matrix2f.java
similarity index 100%
rename from graphics/java/android/renderscript/Matrix2f.java
rename to rs/java/android/renderscript/Matrix2f.java
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/rs/java/android/renderscript/Matrix3f.java
similarity index 100%
rename from graphics/java/android/renderscript/Matrix3f.java
rename to rs/java/android/renderscript/Matrix3f.java
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/rs/java/android/renderscript/Matrix4f.java
similarity index 100%
rename from graphics/java/android/renderscript/Matrix4f.java
rename to rs/java/android/renderscript/Matrix4f.java
diff --git a/graphics/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
similarity index 97%
rename from graphics/java/android/renderscript/Mesh.java
rename to rs/java/android/renderscript/Mesh.java
index bca4aa3..9ce3fb2 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -91,7 +91,7 @@
     Allocation[] mIndexBuffers;
     Primitive[] mPrimitives;
 
-    Mesh(int id, RenderScript rs) {
+    Mesh(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -367,7 +367,7 @@
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
                 }
                 vertexBuffers[ct] = alloc;
-                vtx[ct] = alloc.getID(mRS);
+                vtx[ct] = (int)alloc.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
@@ -378,15 +378,15 @@
                 } else if(entry.e != null) {
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
                 }
-                int allocID = (alloc == null) ? 0 : alloc.getID(mRS);
+                long allocID = (alloc == null) ? 0 : alloc.getID(mRS);
                 indexBuffers[ct] = alloc;
                 primitives[ct] = entry.prim;
 
-                idx[ct] = allocID;
+                idx[ct] = (int)allocID;
                 prim[ct] = entry.prim.mID;
             }
 
-            int id = mRS.nMeshCreate(vtx, idx, prim);
+            long id = mRS.nMeshCreate(vtx, idx, prim);
             Mesh newMesh = new Mesh(id, mRS);
             newMesh.mVertexBuffers = vertexBuffers;
             newMesh.mIndexBuffers = indexBuffers;
@@ -517,20 +517,20 @@
             for(int ct = 0; ct < mVertexTypeCount; ct ++) {
                 Entry entry = mVertexTypes[ct];
                 vertexBuffers[ct] = entry.a;
-                vtx[ct] = entry.a.getID(mRS);
+                vtx[ct] = (int)entry.a.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
                 Entry entry = (Entry)mIndexTypes.elementAt(ct);
-                int allocID = (entry.a == null) ? 0 : entry.a.getID(mRS);
+                long allocID = (entry.a == null) ? 0 : entry.a.getID(mRS);
                 indexBuffers[ct] = entry.a;
                 primitives[ct] = entry.prim;
 
-                idx[ct] = allocID;
+                idx[ct] = (int)allocID;
                 prim[ct] = entry.prim.mID;
             }
 
-            int id = mRS.nMeshCreate(vtx, idx, prim);
+            long id = mRS.nMeshCreate(vtx, idx, prim);
             Mesh newMesh = new Mesh(id, mRS);
             newMesh.mVertexBuffers = vertexBuffers;
             newMesh.mIndexBuffers = indexBuffers;
diff --git a/graphics/java/android/renderscript/Path.java b/rs/java/android/renderscript/Path.java
similarity index 92%
rename from graphics/java/android/renderscript/Path.java
rename to rs/java/android/renderscript/Path.java
index 9c4d41b..5cc67de 100644
--- a/graphics/java/android/renderscript/Path.java
+++ b/rs/java/android/renderscript/Path.java
@@ -41,7 +41,7 @@
     float mQuality;
     boolean mCoverageToAlpha;
 
-    Path(int id, RenderScript rs, Primitive p, Allocation vtx, Allocation loop, float q) {
+    Path(long id, RenderScript rs, Primitive p, Allocation vtx, Allocation loop, float q) {
         super(id, rs);
         mVertexBuffer = vtx;
         mLoopBuffer = loop;
@@ -67,7 +67,7 @@
 
 
     public static Path createStaticPath(RenderScript rs, Primitive p, float quality, Allocation vtx) {
-        int id = rs.nPathCreate(p.mID, false, vtx.getID(rs), 0, quality);
+        long id = rs.nPathCreate(p.mID, false, vtx.getID(rs), 0, quality);
         Path newPath = new Path(id, rs, p, null, null, quality);
         return newPath;
     }
diff --git a/graphics/java/android/renderscript/Program.java b/rs/java/android/renderscript/Program.java
similarity index 98%
rename from graphics/java/android/renderscript/Program.java
rename to rs/java/android/renderscript/Program.java
index bc2ca35..3eb9b75 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/rs/java/android/renderscript/Program.java
@@ -74,7 +74,7 @@
     int mTextureCount;
     String mShader;
 
-    Program(int id, RenderScript rs) {
+    Program(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -150,7 +150,7 @@
             a.getType().getID(mRS) != mConstants[slot].getID(mRS)) {
             throw new IllegalArgumentException("Allocation type does not match slot type.");
         }
-        int id = a != null ? a.getID(mRS) : 0;
+        long id = a != null ? a.getID(mRS) : 0;
         mRS.nProgramBindConstants(getID(mRS), slot, id);
     }
 
@@ -172,7 +172,7 @@
             throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot");
         }
 
-        int id = va != null ? va.getID(mRS) : 0;
+        long id = va != null ? va.getID(mRS) : 0;
         mRS.nProgramBindTexture(getID(mRS), slot, id);
     }
 
@@ -192,7 +192,7 @@
             throw new IllegalArgumentException("Slot ID out of range.");
         }
 
-        int id = vs != null ? vs.getID(mRS) : 0;
+        long id = vs != null ? vs.getID(mRS) : 0;
         mRS.nProgramBindSampler(getID(mRS), slot, id);
     }
 
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/rs/java/android/renderscript/ProgramFragment.java
similarity index 89%
rename from graphics/java/android/renderscript/ProgramFragment.java
rename to rs/java/android/renderscript/ProgramFragment.java
index b9ba3fd..5e886a3 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/rs/java/android/renderscript/ProgramFragment.java
@@ -39,7 +39,7 @@
  *
  **/
 public class ProgramFragment extends Program {
-    ProgramFragment(int id, RenderScript rs) {
+    ProgramFragment(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -71,23 +71,23 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID(mRS);
+                tmp[idx++] = (int)mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID(mRS);
+                tmp[idx++] = (int)mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID(mRS);
+                tmp[idx++] = (int)mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = mTextureTypes[i].mID;
+                tmp[idx++] = (int)mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
+            long id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
             ProgramFragment pf = new ProgramFragment(id, mRS);
             initProgram(pf);
             return pf;
diff --git a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
similarity index 96%
rename from graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
rename to rs/java/android/renderscript/ProgramFragmentFixedFunction.java
index 8ae1777..22aed0a 100644
--- a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -31,7 +31,7 @@
  *
  **/
 public class ProgramFragmentFixedFunction extends ProgramFragment {
-    ProgramFragmentFixedFunction(int id, RenderScript rs) {
+    ProgramFragmentFixedFunction(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -58,23 +58,23 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID(mRS);
+                tmp[idx++] = (int)mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID(mRS);
+                tmp[idx++] = (int)mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID(mRS);
+                tmp[idx++] = (int)mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = mTextureTypes[i].mID;
+                tmp[idx++] = (int)mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
+            long id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
             ProgramFragmentFixedFunction pf = new ProgramFragmentFixedFunction(id, mRS);
             initProgram(pf);
             return pf;
diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/rs/java/android/renderscript/ProgramRaster.java
similarity index 96%
rename from graphics/java/android/renderscript/ProgramRaster.java
rename to rs/java/android/renderscript/ProgramRaster.java
index 216cb4e..e294b05 100644
--- a/graphics/java/android/renderscript/ProgramRaster.java
+++ b/rs/java/android/renderscript/ProgramRaster.java
@@ -54,7 +54,7 @@
     boolean mPointSprite;
     CullMode mCullMode;
 
-    ProgramRaster(int id, RenderScript rs) {
+    ProgramRaster(long id, RenderScript rs) {
         super(id, rs);
 
         mPointSprite = false;
@@ -154,7 +154,7 @@
          */
         public ProgramRaster create() {
             mRS.validate();
-            int id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID);
+            long id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID);
             ProgramRaster programRaster = new ProgramRaster(id, mRS);
             programRaster.mPointSprite = mPointSprite;
             programRaster.mCullMode = mCullMode;
diff --git a/graphics/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
similarity index 98%
rename from graphics/java/android/renderscript/ProgramStore.java
rename to rs/java/android/renderscript/ProgramStore.java
index dac9e76..969cc25 100644
--- a/graphics/java/android/renderscript/ProgramStore.java
+++ b/rs/java/android/renderscript/ProgramStore.java
@@ -146,7 +146,7 @@
     BlendDstFunc mBlendDst;
     boolean mDither;
 
-    ProgramStore(int id, RenderScript rs) {
+    ProgramStore(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -421,7 +421,7 @@
         */
         public ProgramStore create() {
             mRS.validate();
-            int id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
+            long id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
                                              mDepthMask, mDither,
                                              mBlendSrc.mID, mBlendDst.mID, mDepthFunc.mID);
             ProgramStore programStore = new ProgramStore(id, mRS);
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/rs/java/android/renderscript/ProgramVertex.java
similarity index 93%
rename from graphics/java/android/renderscript/ProgramVertex.java
rename to rs/java/android/renderscript/ProgramVertex.java
index 1c5a191..b6886e1 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/rs/java/android/renderscript/ProgramVertex.java
@@ -53,7 +53,7 @@
  **/
 public class ProgramVertex extends Program {
 
-    ProgramVertex(int id, RenderScript rs) {
+    ProgramVertex(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -132,23 +132,23 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID(mRS);
+                tmp[idx++] = (int)mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID(mRS);
+                tmp[idx++] = (int)mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID(mRS);
+                tmp[idx++] = (int)mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = mTextureTypes[i].mID;
+                tmp[idx++] = (int)mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
+            long id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
             ProgramVertex pv = new ProgramVertex(id, mRS);
             initProgram(pv);
             return pv;
diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
similarity index 95%
rename from graphics/java/android/renderscript/ProgramVertexFixedFunction.java
rename to rs/java/android/renderscript/ProgramVertexFixedFunction.java
index ad486f3..c479c77 100644
--- a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -31,7 +31,7 @@
  **/
 public class ProgramVertexFixedFunction extends ProgramVertex {
 
-    ProgramVertexFixedFunction(int id, RenderScript rs) {
+    ProgramVertexFixedFunction(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -85,23 +85,23 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID(mRS);
+                tmp[idx++] = (int)mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID(mRS);
+                tmp[idx++] = (int)mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID(mRS);
+                tmp[idx++] = (int)mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = mTextureTypes[i].mID;
+                tmp[idx++] = (int)mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
+            long id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
             ProgramVertexFixedFunction pv = new ProgramVertexFixedFunction(id, mRS);
             initProgram(pv);
             return pv;
diff --git a/graphics/java/android/renderscript/RSDriverException.java b/rs/java/android/renderscript/RSDriverException.java
similarity index 100%
rename from graphics/java/android/renderscript/RSDriverException.java
rename to rs/java/android/renderscript/RSDriverException.java
diff --git a/graphics/java/android/renderscript/RSIllegalArgumentException.java b/rs/java/android/renderscript/RSIllegalArgumentException.java
similarity index 100%
rename from graphics/java/android/renderscript/RSIllegalArgumentException.java
rename to rs/java/android/renderscript/RSIllegalArgumentException.java
diff --git a/graphics/java/android/renderscript/RSInvalidStateException.java b/rs/java/android/renderscript/RSInvalidStateException.java
similarity index 100%
rename from graphics/java/android/renderscript/RSInvalidStateException.java
rename to rs/java/android/renderscript/RSInvalidStateException.java
diff --git a/graphics/java/android/renderscript/RSRuntimeException.java b/rs/java/android/renderscript/RSRuntimeException.java
similarity index 100%
rename from graphics/java/android/renderscript/RSRuntimeException.java
rename to rs/java/android/renderscript/RSRuntimeException.java
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/rs/java/android/renderscript/RSSurfaceView.java
similarity index 100%
rename from graphics/java/android/renderscript/RSSurfaceView.java
rename to rs/java/android/renderscript/RSSurfaceView.java
diff --git a/graphics/java/android/renderscript/RSTextureView.java b/rs/java/android/renderscript/RSTextureView.java
similarity index 100%
rename from graphics/java/android/renderscript/RSTextureView.java
rename to rs/java/android/renderscript/RSTextureView.java
diff --git a/graphics/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
similarity index 62%
rename from graphics/java/android/renderscript/RenderScript.java
rename to rs/java/android/renderscript/RenderScript.java
index 7d4a5c4..b211c5a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -19,6 +19,7 @@
 import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -91,17 +92,31 @@
     }
 
     // Non-threadsafe functions.
-    native int  nDeviceCreate();
-    native void nDeviceDestroy(int dev);
-    native void nDeviceSetConfig(int dev, int param, int value);
-    native int nContextGetUserMessage(int con, int[] data);
-    native String nContextGetErrorMessage(int con);
-    native int  nContextPeekMessage(int con, int[] subID);
-    native void nContextInitToClient(int con);
-    native void nContextDeinitToClient(int con);
+    native long  nDeviceCreate();
+    native void nDeviceDestroy(long dev);
+    native void nDeviceSetConfig(long dev, int param, int value);
+    native int nContextGetUserMessage(long con, int[] data);
+    native String nContextGetErrorMessage(long con);
+    native int  nContextPeekMessage(long con, int[] subID);
+    native void nContextInitToClient(long con);
+    native void nContextDeinitToClient(long con);
 
     static File mCacheDir;
 
+    // this should be a monotonically increasing ID
+    // used in conjunction with the API version of a device
+    static final long sMinorID = 1;
+
+    /**
+     * Returns an identifier that can be used to identify a particular
+     * minor version of RS.
+     *
+     * @hide
+     */
+    public static long getMinorID() {
+        return sMinorID;
+    }
+
      /**
      * Sets the directory to use as a persistent storage for the
      * renderscript object file cache.
@@ -151,16 +166,17 @@
     }
 
     ContextType mContextType;
+    ReentrantReadWriteLock mRWLock;
 
     // Methods below are wrapped to protect the non-threadsafe
     // lockless fifo.
-    native int  rsnContextCreateGL(int dev, int ver, int sdkVer,
+    native long  rsnContextCreateGL(long dev, int ver, int sdkVer,
                  int colorMin, int colorPref,
                  int alphaMin, int alphaPref,
                  int depthMin, int depthPref,
                  int stencilMin, int stencilPref,
                  int samplesMin, int samplesPref, float samplesQ, int dpi);
-    synchronized int nContextCreateGL(int dev, int ver, int sdkVer,
+    synchronized long nContextCreateGL(long dev, int ver, int sdkVer,
                  int colorMin, int colorPref,
                  int alphaMin, int alphaPref,
                  int depthMin, int depthPref,
@@ -171,100 +187,113 @@
                                   stencilMin, stencilPref,
                                   samplesMin, samplesPref, samplesQ, dpi);
     }
-    native int  rsnContextCreate(int dev, int ver, int sdkVer, int contextType);
-    synchronized int nContextCreate(int dev, int ver, int sdkVer, int contextType) {
+    native long  rsnContextCreate(long dev, int ver, int sdkVer, int contextType);
+    synchronized long nContextCreate(long dev, int ver, int sdkVer, int contextType) {
         return rsnContextCreate(dev, ver, sdkVer, contextType);
     }
-    native void rsnContextDestroy(int con);
+    native void rsnContextDestroy(long con);
     synchronized void nContextDestroy() {
         validate();
-        rsnContextDestroy(mContext);
+
+        // take teardown lock
+        // teardown lock can only be taken when no objects are being destroyed
+        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
+        wlock.lock();
+
+        long curCon = mContext;
+        // context is considered dead as of this point
+        mContext = 0;
+
+        wlock.unlock();
+        rsnContextDestroy(curCon);
     }
-    native void rsnContextSetSurface(int con, int w, int h, Surface sur);
+    native void rsnContextSetSurface(long con, int w, int h, Surface sur);
     synchronized void nContextSetSurface(int w, int h, Surface sur) {
         validate();
         rsnContextSetSurface(mContext, w, h, sur);
     }
-    native void rsnContextSetSurfaceTexture(int con, int w, int h, SurfaceTexture sur);
+    native void rsnContextSetSurfaceTexture(long con, int w, int h, SurfaceTexture sur);
     synchronized void nContextSetSurfaceTexture(int w, int h, SurfaceTexture sur) {
         validate();
         rsnContextSetSurfaceTexture(mContext, w, h, sur);
     }
-    native void rsnContextSetPriority(int con, int p);
+    native void rsnContextSetPriority(long con, int p);
     synchronized void nContextSetPriority(int p) {
         validate();
         rsnContextSetPriority(mContext, p);
     }
-    native void rsnContextDump(int con, int bits);
+    native void rsnContextDump(long con, int bits);
     synchronized void nContextDump(int bits) {
         validate();
         rsnContextDump(mContext, bits);
     }
-    native void rsnContextFinish(int con);
+    native void rsnContextFinish(long con);
     synchronized void nContextFinish() {
         validate();
         rsnContextFinish(mContext);
     }
 
-    native void rsnContextSendMessage(int con, int id, int[] data);
+    native void rsnContextSendMessage(long con, int id, int[] data);
     synchronized void nContextSendMessage(int id, int[] data) {
         validate();
         rsnContextSendMessage(mContext, id, data);
     }
 
-    native void rsnContextBindRootScript(int con, int script);
+    native void rsnContextBindRootScript(long con, int script);
     synchronized void nContextBindRootScript(int script) {
         validate();
         rsnContextBindRootScript(mContext, script);
     }
-    native void rsnContextBindSampler(int con, int sampler, int slot);
+    native void rsnContextBindSampler(long con, int sampler, int slot);
     synchronized void nContextBindSampler(int sampler, int slot) {
         validate();
         rsnContextBindSampler(mContext, sampler, slot);
     }
-    native void rsnContextBindProgramStore(int con, int pfs);
+    native void rsnContextBindProgramStore(long con, int pfs);
     synchronized void nContextBindProgramStore(int pfs) {
         validate();
         rsnContextBindProgramStore(mContext, pfs);
     }
-    native void rsnContextBindProgramFragment(int con, int pf);
+    native void rsnContextBindProgramFragment(long con, int pf);
     synchronized void nContextBindProgramFragment(int pf) {
         validate();
         rsnContextBindProgramFragment(mContext, pf);
     }
-    native void rsnContextBindProgramVertex(int con, int pv);
+    native void rsnContextBindProgramVertex(long con, int pv);
     synchronized void nContextBindProgramVertex(int pv) {
         validate();
         rsnContextBindProgramVertex(mContext, pv);
     }
-    native void rsnContextBindProgramRaster(int con, int pr);
+    native void rsnContextBindProgramRaster(long con, int pr);
     synchronized void nContextBindProgramRaster(int pr) {
         validate();
         rsnContextBindProgramRaster(mContext, pr);
     }
-    native void rsnContextPause(int con);
+    native void rsnContextPause(long con);
     synchronized void nContextPause() {
         validate();
         rsnContextPause(mContext);
     }
-    native void rsnContextResume(int con);
+    native void rsnContextResume(long con);
     synchronized void nContextResume() {
         validate();
         rsnContextResume(mContext);
     }
 
-    native void rsnAssignName(int con, int obj, byte[] name);
-    synchronized void nAssignName(int obj, byte[] name) {
+    native void rsnAssignName(long con, long obj, byte[] name);
+    synchronized void nAssignName(long obj, byte[] name) {
         validate();
         rsnAssignName(mContext, obj, name);
     }
-    native String rsnGetName(int con, int obj);
-    synchronized String nGetName(int obj) {
+    native String rsnGetName(long con, long obj);
+    synchronized String nGetName(long obj) {
         validate();
         return rsnGetName(mContext, obj);
     }
-    native void rsnObjDestroy(int con, int id);
-    synchronized void nObjDestroy(int id) {
+
+    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
+    native void rsnObjDestroy(long con, long id);
+    void nObjDestroy(long id) {
         // There is a race condition here.  The calling code may be run
         // by the gc while teardown is occuring.  This protects againts
         // deleting dead objects.
@@ -273,156 +302,140 @@
         }
     }
 
-    native int  rsnElementCreate(int con, int type, int kind, boolean norm, int vecSize);
-    synchronized int nElementCreate(int type, int kind, boolean norm, int vecSize) {
+    native long rsnElementCreate(long con, long type, int kind, boolean norm, int vecSize);
+    synchronized long nElementCreate(long type, int kind, boolean norm, int vecSize) {
         validate();
         return rsnElementCreate(mContext, type, kind, norm, vecSize);
     }
-    native int  rsnElementCreate2(int con, int[] elements, String[] names, int[] arraySizes);
-    synchronized int nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
+    native long rsnElementCreate2(long con, int[]elements, String[] names, int[] arraySizes);
+    synchronized long nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
         validate();
         return rsnElementCreate2(mContext, elements, names, arraySizes);
     }
-    native void rsnElementGetNativeData(int con, int id, int[] elementData);
-    synchronized void nElementGetNativeData(int id, int[] elementData) {
+    native void rsnElementGetNativeData(long con, long id, int[] elementData);
+    synchronized void nElementGetNativeData(long id, int[] elementData) {
         validate();
         rsnElementGetNativeData(mContext, id, elementData);
     }
-    native void rsnElementGetSubElements(int con, int id,
+    native void rsnElementGetSubElements(long con, long id,
                                          int[] IDs, String[] names, int[] arraySizes);
-    synchronized void nElementGetSubElements(int id, int[] IDs, String[] names, int[] arraySizes) {
+    synchronized void nElementGetSubElements(long id, int[] IDs, String[] names, int[] arraySizes) {
         validate();
         rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
     }
 
-    native int rsnTypeCreate(int con, int eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
-    synchronized int nTypeCreate(int eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
+    native long rsnTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
+    synchronized long nTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
         validate();
         return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
     }
-    native void rsnTypeGetNativeData(int con, int id, int[] typeData);
-    synchronized void nTypeGetNativeData(int id, int[] typeData) {
+    native void rsnTypeGetNativeData(long con, long id, int[] typeData);
+    synchronized void nTypeGetNativeData(long id, int[] typeData) {
         validate();
         rsnTypeGetNativeData(mContext, id, typeData);
     }
 
-    native int  rsnAllocationCreateTyped(int con, int type, int mip, int usage, int pointer);
-    synchronized int nAllocationCreateTyped(int type, int mip, int usage, int pointer) {
+    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, int pointer);
+    synchronized long nAllocationCreateTyped(long type, int mip, int usage, int pointer) {
         validate();
         return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
     }
-    native int  rsnAllocationCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
-    synchronized int nAllocationCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
+    native long rsnAllocationCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
+    synchronized long nAllocationCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
         validate();
         return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
     }
 
-    native int  rsnAllocationCreateBitmapBackedAllocation(int con, int type, int mip, Bitmap bmp, int usage);
-    synchronized int nAllocationCreateBitmapBackedAllocation(int type, int mip, Bitmap bmp, int usage) {
+    native long rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, Bitmap bmp, int usage);
+    synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp, int usage) {
         validate();
         return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
     }
 
-
-    native int  rsnAllocationCubeCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
-    synchronized int nAllocationCubeCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
+    native long rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, Bitmap bmp, int usage);
+    synchronized long nAllocationCubeCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
         validate();
         return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
     }
-    native int  rsnAllocationCreateBitmapRef(int con, int type, Bitmap bmp);
-    synchronized int nAllocationCreateBitmapRef(int type, Bitmap bmp) {
+    native long  rsnAllocationCreateBitmapRef(long con, long type, Bitmap bmp);
+    synchronized long nAllocationCreateBitmapRef(long type, Bitmap bmp) {
         validate();
         return rsnAllocationCreateBitmapRef(mContext, type, bmp);
     }
-    native int  rsnAllocationCreateFromAssetStream(int con, int mips, int assetStream, int usage);
-    synchronized int nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
+    native long  rsnAllocationCreateFromAssetStream(long con, int mips, int assetStream, int usage);
+    synchronized long nAllocationCreateFromAssetStream(int mips, int assetStream, int usage) {
         validate();
         return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
     }
 
-    native void  rsnAllocationCopyToBitmap(int con, int alloc, Bitmap bmp);
-    synchronized void nAllocationCopyToBitmap(int alloc, Bitmap bmp) {
+    native void  rsnAllocationCopyToBitmap(long con, long alloc, Bitmap bmp);
+    synchronized void nAllocationCopyToBitmap(long alloc, Bitmap bmp) {
         validate();
         rsnAllocationCopyToBitmap(mContext, alloc, bmp);
     }
 
 
-    native void rsnAllocationSyncAll(int con, int alloc, int src);
-    synchronized void nAllocationSyncAll(int alloc, int src) {
+    native void rsnAllocationSyncAll(long con, long alloc, int src);
+    synchronized void nAllocationSyncAll(long alloc, int src) {
         validate();
         rsnAllocationSyncAll(mContext, alloc, src);
     }
-    native Surface rsnAllocationGetSurface(int con, int alloc);
-    synchronized Surface nAllocationGetSurface(int alloc) {
+    native Surface rsnAllocationGetSurface(long con, long alloc);
+    synchronized Surface nAllocationGetSurface(long alloc) {
         validate();
         return rsnAllocationGetSurface(mContext, alloc);
     }
-    native void rsnAllocationSetSurface(int con, int alloc, Surface sur);
-    synchronized void nAllocationSetSurface(int alloc, Surface sur) {
+    native void rsnAllocationSetSurface(long con, long alloc, Surface sur);
+    synchronized void nAllocationSetSurface(long alloc, Surface sur) {
         validate();
         rsnAllocationSetSurface(mContext, alloc, sur);
     }
-    native void rsnAllocationIoSend(int con, int alloc);
-    synchronized void nAllocationIoSend(int alloc) {
+    native void rsnAllocationIoSend(long con, long alloc);
+    synchronized void nAllocationIoSend(long alloc) {
         validate();
         rsnAllocationIoSend(mContext, alloc);
     }
-    native void rsnAllocationIoReceive(int con, int alloc);
-    synchronized void nAllocationIoReceive(int alloc) {
+    native void rsnAllocationIoReceive(long con, long alloc);
+    synchronized void nAllocationIoReceive(long alloc) {
         validate();
         rsnAllocationIoReceive(mContext, alloc);
     }
 
 
-    native void rsnAllocationGenerateMipmaps(int con, int alloc);
-    synchronized void nAllocationGenerateMipmaps(int alloc) {
+    native void rsnAllocationGenerateMipmaps(long con, long alloc);
+    synchronized void nAllocationGenerateMipmaps(long alloc) {
         validate();
         rsnAllocationGenerateMipmaps(mContext, alloc);
     }
-    native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
-    synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
+    native void  rsnAllocationCopyFromBitmap(long con, long alloc, Bitmap bmp);
+    synchronized void nAllocationCopyFromBitmap(long alloc, Bitmap bmp) {
         validate();
         rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
     }
 
 
-    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, int[] d, int sizeBytes);
-    synchronized void nAllocationData1D(int id, int off, int mip, int count, int[] d, int sizeBytes) {
+    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, Object d, int sizeBytes, int dt);
+    synchronized void nAllocationData1D(long id, int off, int mip, int count, Object d, int sizeBytes, Element.DataType dt) {
         validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
-    }
-    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, short[] d, int sizeBytes);
-    synchronized void nAllocationData1D(int id, int off, int mip, int count, short[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
-    }
-    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, byte[] d, int sizeBytes);
-    synchronized void nAllocationData1D(int id, int off, int mip, int count, byte[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
-    }
-    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, float[] d, int sizeBytes);
-    synchronized void nAllocationData1D(int id, int off, int mip, int count, float[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
+        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID);
     }
 
-    native void rsnAllocationElementData1D(int con, int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
-    synchronized void nAllocationElementData1D(int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
+    native void rsnAllocationElementData1D(long con,long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
+    synchronized void nAllocationElementData1D(long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
         validate();
         rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
     }
 
-    native void rsnAllocationData2D(int con,
-                                    int dstAlloc, int dstXoff, int dstYoff,
+    native void rsnAllocationData2D(long con,
+                                    long dstAlloc, int dstXoff, int dstYoff,
                                     int dstMip, int dstFace,
                                     int width, int height,
-                                    int srcAlloc, int srcXoff, int srcYoff,
+                                    long srcAlloc, int srcXoff, int srcYoff,
                                     int srcMip, int srcFace);
-    synchronized void nAllocationData2D(int dstAlloc, int dstXoff, int dstYoff,
+    synchronized void nAllocationData2D(long dstAlloc, int dstXoff, int dstYoff,
                                         int dstMip, int dstFace,
                                         int width, int height,
-                                        int srcAlloc, int srcXoff, int srcYoff,
+                                        long srcAlloc, int srcXoff, int srcYoff,
                                         int srcMip, int srcFace) {
         validate();
         rsnAllocationData2D(mContext,
@@ -433,42 +446,30 @@
                             srcMip, srcFace);
     }
 
-    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
-    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes) {
+    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face,
+                                    int w, int h, Object d, int sizeBytes, int dt);
+    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face,
+                                        int w, int h, Object d, int sizeBytes, Element.DataType dt) {
         validate();
-        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID);
     }
-    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes);
-    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
-    }
-    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes);
-    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
-    }
-    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes);
-    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
-    }
-    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, Bitmap b);
-    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, Bitmap b) {
+
+    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, Bitmap b);
+    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face, Bitmap b) {
         validate();
         rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
     }
 
-    native void rsnAllocationData3D(int con,
-                                    int dstAlloc, int dstXoff, int dstYoff, int dstZoff,
+    native void rsnAllocationData3D(long con,
+                                    long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
                                     int dstMip,
                                     int width, int height, int depth,
-                                    int srcAlloc, int srcXoff, int srcYoff, int srcZoff,
+                                    long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
                                     int srcMip);
-    synchronized void nAllocationData3D(int dstAlloc, int dstXoff, int dstYoff, int dstZoff,
+    synchronized void nAllocationData3D(long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
                                         int dstMip,
                                         int width, int height, int depth,
-                                        int srcAlloc, int srcXoff, int srcYoff, int srcZoff,
+                                        long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
                                         int srcMip) {
         validate();
         rsnAllocationData3D(mContext,
@@ -477,130 +478,118 @@
                             srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
     }
 
-    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes);
-    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes) {
+    native void rsnAllocationData3D(long con, long id, int xoff, int yoff, int zoff, int mip,
+                                    int w, int h, int depth, Object d, int sizeBytes, int dt);
+    synchronized void nAllocationData3D(long id, int xoff, int yoff, int zoff, int mip,
+                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt) {
         validate();
-        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
-    }
-    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes);
-    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
-    }
-    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes);
-    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
-    }
-    native void rsnAllocationData3D(int con, int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes);
-    synchronized void nAllocationData3D(int id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
+        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes, dt.mID);
     }
 
+    native void rsnAllocationRead(long con, long id, Object d, int dt);
+    synchronized void nAllocationRead(long id, Object d, Element.DataType dt) {
+        validate();
+        rsnAllocationRead(mContext, id, d, dt.mID);
+    }
 
-    native void rsnAllocationRead(int con, int id, byte[] d);
-    synchronized void nAllocationRead(int id, byte[] d) {
+    native void rsnAllocationRead1D(long con, long id, int off, int mip, int count, Object d,
+                                    int sizeBytes, int dt);
+    synchronized void nAllocationRead1D(long id, int off, int mip, int count, Object d,
+                                        int sizeBytes, Element.DataType dt) {
         validate();
-        rsnAllocationRead(mContext, id, d);
+        rsnAllocationRead1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID);
     }
-    native void rsnAllocationRead(int con, int id, short[] d);
-    synchronized void nAllocationRead(int id, short[] d) {
+
+    native void rsnAllocationRead2D(long con, long id, int xoff, int yoff, int mip, int face,
+                                    int w, int h, Object d, int sizeBytes, int dt);
+    synchronized void nAllocationRead2D(long id, int xoff, int yoff, int mip, int face,
+                                        int w, int h, Object d, int sizeBytes, Element.DataType dt) {
         validate();
-        rsnAllocationRead(mContext, id, d);
+        rsnAllocationRead2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID);
     }
-    native void rsnAllocationRead(int con, int id, int[] d);
-    synchronized void nAllocationRead(int id, int[] d) {
-        validate();
-        rsnAllocationRead(mContext, id, d);
-    }
-    native void rsnAllocationRead(int con, int id, float[] d);
-    synchronized void nAllocationRead(int id, float[] d) {
-        validate();
-        rsnAllocationRead(mContext, id, d);
-    }
-    native int  rsnAllocationGetType(int con, int id);
-    synchronized int nAllocationGetType(int id) {
+
+    native long  rsnAllocationGetType(long con, long id);
+    synchronized long nAllocationGetType(long id) {
         validate();
         return rsnAllocationGetType(mContext, id);
     }
 
-    native void rsnAllocationResize1D(int con, int id, int dimX);
-    synchronized void nAllocationResize1D(int id, int dimX) {
+    native void rsnAllocationResize1D(long con, long id, int dimX);
+    synchronized void nAllocationResize1D(long id, int dimX) {
         validate();
         rsnAllocationResize1D(mContext, id, dimX);
     }
 
-    native int  rsnFileA3DCreateFromAssetStream(int con, int assetStream);
-    synchronized int nFileA3DCreateFromAssetStream(int assetStream) {
+    native long rsnFileA3DCreateFromAssetStream(long con, long assetStream);
+    synchronized long nFileA3DCreateFromAssetStream(long assetStream) {
         validate();
         return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
     }
-    native int  rsnFileA3DCreateFromFile(int con, String path);
-    synchronized int nFileA3DCreateFromFile(String path) {
+    native long rsnFileA3DCreateFromFile(long con, String path);
+    synchronized long nFileA3DCreateFromFile(String path) {
         validate();
         return rsnFileA3DCreateFromFile(mContext, path);
     }
-    native int  rsnFileA3DCreateFromAsset(int con, AssetManager mgr, String path);
-    synchronized int nFileA3DCreateFromAsset(AssetManager mgr, String path) {
+    native long rsnFileA3DCreateFromAsset(long con, AssetManager mgr, String path);
+    synchronized long nFileA3DCreateFromAsset(AssetManager mgr, String path) {
         validate();
         return rsnFileA3DCreateFromAsset(mContext, mgr, path);
     }
-    native int  rsnFileA3DGetNumIndexEntries(int con, int fileA3D);
-    synchronized int nFileA3DGetNumIndexEntries(int fileA3D) {
+    native int  rsnFileA3DGetNumIndexEntries(long con, long fileA3D);
+    synchronized int nFileA3DGetNumIndexEntries(long fileA3D) {
         validate();
         return rsnFileA3DGetNumIndexEntries(mContext, fileA3D);
     }
-    native void rsnFileA3DGetIndexEntries(int con, int fileA3D, int numEntries, int[] IDs, String[] names);
-    synchronized void nFileA3DGetIndexEntries(int fileA3D, int numEntries, int[] IDs, String[] names) {
+    native void rsnFileA3DGetIndexEntries(long con, long fileA3D, int numEntries, int[] IDs, String[] names);
+    synchronized void nFileA3DGetIndexEntries(long fileA3D, int numEntries, int[] IDs, String[] names) {
         validate();
         rsnFileA3DGetIndexEntries(mContext, fileA3D, numEntries, IDs, names);
     }
-    native int  rsnFileA3DGetEntryByIndex(int con, int fileA3D, int index);
-    synchronized int nFileA3DGetEntryByIndex(int fileA3D, int index) {
+    native long rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
+    synchronized long nFileA3DGetEntryByIndex(long fileA3D, int index) {
         validate();
         return rsnFileA3DGetEntryByIndex(mContext, fileA3D, index);
     }
 
-    native int  rsnFontCreateFromFile(int con, String fileName, float size, int dpi);
-    synchronized int nFontCreateFromFile(String fileName, float size, int dpi) {
+    native long rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
+    synchronized long nFontCreateFromFile(String fileName, float size, int dpi) {
         validate();
         return rsnFontCreateFromFile(mContext, fileName, size, dpi);
     }
-    native int  rsnFontCreateFromAssetStream(int con, String name, float size, int dpi, int assetStream);
-    synchronized int nFontCreateFromAssetStream(String name, float size, int dpi, int assetStream) {
+    native long rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, long assetStream);
+    synchronized long nFontCreateFromAssetStream(String name, float size, int dpi, long assetStream) {
         validate();
         return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
     }
-    native int  rsnFontCreateFromAsset(int con, AssetManager mgr, String path, float size, int dpi);
-    synchronized int nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
+    native long rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
+    synchronized long nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
         validate();
         return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
     }
 
 
-    native void rsnScriptBindAllocation(int con, int script, int alloc, int slot);
-    synchronized void nScriptBindAllocation(int script, int alloc, int slot) {
+    native void rsnScriptBindAllocation(long con, long script, long alloc, int slot);
+    synchronized void nScriptBindAllocation(long script, long alloc, int slot) {
         validate();
         rsnScriptBindAllocation(mContext, script, alloc, slot);
     }
-    native void rsnScriptSetTimeZone(int con, int script, byte[] timeZone);
-    synchronized void nScriptSetTimeZone(int script, byte[] timeZone) {
+    native void rsnScriptSetTimeZone(long con, long script, byte[] timeZone);
+    synchronized void nScriptSetTimeZone(long script, byte[] timeZone) {
         validate();
         rsnScriptSetTimeZone(mContext, script, timeZone);
     }
-    native void rsnScriptInvoke(int con, int id, int slot);
-    synchronized void nScriptInvoke(int id, int slot) {
+    native void rsnScriptInvoke(long con, long id, int slot);
+    synchronized void nScriptInvoke(long id, int slot) {
         validate();
         rsnScriptInvoke(mContext, id, slot);
     }
-    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout, byte[] params);
-    native void rsnScriptForEach(int con, int id, int slot, int ain, int aout);
-    native void rsnScriptForEachClipped(int con, int id, int slot, int ain, int aout, byte[] params,
+    native void rsnScriptForEach(long con, long id, int slot, long ain, long aout, byte[] params);
+    native void rsnScriptForEach(long con, long id, int slot, long ain, long aout);
+    native void rsnScriptForEachClipped(long con, long id, int slot, long ain, long aout, byte[] params,
                                         int xstart, int xend, int ystart, int yend, int zstart, int zend);
-    native void rsnScriptForEachClipped(int con, int id, int slot, int ain, int aout,
+    native void rsnScriptForEachClipped(long con, long id, int slot, long ain, long aout,
                                         int xstart, int xend, int ystart, int yend, int zstart, int zend);
-    synchronized void nScriptForEach(int id, int slot, int ain, int aout, byte[] params) {
+    synchronized void nScriptForEach(long id, int slot, long ain, long aout, byte[] params) {
         validate();
         if (params == null) {
             rsnScriptForEach(mContext, id, slot, ain, aout);
@@ -609,7 +598,7 @@
         }
     }
 
-    synchronized void nScriptForEachClipped(int id, int slot, int ain, int aout, byte[] params,
+    synchronized void nScriptForEachClipped(long id, int slot, long ain, long aout, byte[] params,
                                             int xstart, int xend, int ystart, int yend, int zstart, int zend) {
         validate();
         if (params == null) {
@@ -619,138 +608,138 @@
         }
     }
 
-    native void rsnScriptInvokeV(int con, int id, int slot, byte[] params);
-    synchronized void nScriptInvokeV(int id, int slot, byte[] params) {
+    native void rsnScriptInvokeV(long con, long id, int slot, byte[] params);
+    synchronized void nScriptInvokeV(long id, int slot, byte[] params) {
         validate();
         rsnScriptInvokeV(mContext, id, slot, params);
     }
 
-    native void rsnScriptSetVarI(int con, int id, int slot, int val);
-    synchronized void nScriptSetVarI(int id, int slot, int val) {
+    native void rsnScriptSetVarI(long con, long id, int slot, int val);
+    synchronized void nScriptSetVarI(long id, int slot, int val) {
         validate();
         rsnScriptSetVarI(mContext, id, slot, val);
     }
-    native int rsnScriptGetVarI(int con, int id, int slot);
-    synchronized int nScriptGetVarI(int id, int slot) {
+    native int rsnScriptGetVarI(long con, long id, int slot);
+    synchronized int nScriptGetVarI(long id, int slot) {
         validate();
         return rsnScriptGetVarI(mContext, id, slot);
     }
 
-    native void rsnScriptSetVarJ(int con, int id, int slot, long val);
-    synchronized void nScriptSetVarJ(int id, int slot, long val) {
+    native void rsnScriptSetVarJ(long con, long id, int slot, long val);
+    synchronized void nScriptSetVarJ(long id, int slot, long val) {
         validate();
         rsnScriptSetVarJ(mContext, id, slot, val);
     }
-    native long rsnScriptGetVarJ(int con, int id, int slot);
-    synchronized long nScriptGetVarJ(int id, int slot) {
+    native long rsnScriptGetVarJ(long con, long id, int slot);
+    synchronized long nScriptGetVarJ(long id, int slot) {
         validate();
         return rsnScriptGetVarJ(mContext, id, slot);
     }
 
-    native void rsnScriptSetVarF(int con, int id, int slot, float val);
-    synchronized void nScriptSetVarF(int id, int slot, float val) {
+    native void rsnScriptSetVarF(long con, long id, int slot, float val);
+    synchronized void nScriptSetVarF(long id, int slot, float val) {
         validate();
         rsnScriptSetVarF(mContext, id, slot, val);
     }
-    native float rsnScriptGetVarF(int con, int id, int slot);
-    synchronized float nScriptGetVarF(int id, int slot) {
+    native float rsnScriptGetVarF(long con, long id, int slot);
+    synchronized float nScriptGetVarF(long id, int slot) {
         validate();
         return rsnScriptGetVarF(mContext, id, slot);
     }
-    native void rsnScriptSetVarD(int con, int id, int slot, double val);
-    synchronized void nScriptSetVarD(int id, int slot, double val) {
+    native void rsnScriptSetVarD(long con, long id, int slot, double val);
+    synchronized void nScriptSetVarD(long id, int slot, double val) {
         validate();
         rsnScriptSetVarD(mContext, id, slot, val);
     }
-    native double rsnScriptGetVarD(int con, int id, int slot);
-    synchronized double nScriptGetVarD(int id, int slot) {
+    native double rsnScriptGetVarD(long con, long id, int slot);
+    synchronized double nScriptGetVarD(long id, int slot) {
         validate();
         return rsnScriptGetVarD(mContext, id, slot);
     }
-    native void rsnScriptSetVarV(int con, int id, int slot, byte[] val);
-    synchronized void nScriptSetVarV(int id, int slot, byte[] val) {
+    native void rsnScriptSetVarV(long con, long id, int slot, byte[] val);
+    synchronized void nScriptSetVarV(long id, int slot, byte[] val) {
         validate();
         rsnScriptSetVarV(mContext, id, slot, val);
     }
-    native void rsnScriptGetVarV(int con, int id, int slot, byte[] val);
-    synchronized void nScriptGetVarV(int id, int slot, byte[] val) {
+    native void rsnScriptGetVarV(long con, long id, int slot, byte[] val);
+    synchronized void nScriptGetVarV(long id, int slot, byte[] val) {
         validate();
         rsnScriptGetVarV(mContext, id, slot, val);
     }
-    native void rsnScriptSetVarVE(int con, int id, int slot, byte[] val,
-                                  int e, int[] dims);
-    synchronized void nScriptSetVarVE(int id, int slot, byte[] val,
-                                      int e, int[] dims) {
+    native void rsnScriptSetVarVE(long con, long id, int slot, byte[] val,
+                                  long e, int[] dims);
+    synchronized void nScriptSetVarVE(long id, int slot, byte[] val,
+                                      long e, int[] dims) {
         validate();
         rsnScriptSetVarVE(mContext, id, slot, val, e, dims);
     }
-    native void rsnScriptSetVarObj(int con, int id, int slot, int val);
-    synchronized void nScriptSetVarObj(int id, int slot, int val) {
+    native void rsnScriptSetVarObj(long con, long id, int slot, long val);
+    synchronized void nScriptSetVarObj(long id, int slot, long val) {
         validate();
         rsnScriptSetVarObj(mContext, id, slot, val);
     }
 
-    native int  rsnScriptCCreate(int con, String resName, String cacheDir,
+    native long rsnScriptCCreate(long con, String resName, String cacheDir,
                                  byte[] script, int length);
-    synchronized int nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
+    synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
         validate();
         return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
     }
 
-    native int  rsnScriptIntrinsicCreate(int con, int id, int eid);
-    synchronized int nScriptIntrinsicCreate(int id, int eid) {
+    native long rsnScriptIntrinsicCreate(long con, int id, long eid);
+    synchronized long nScriptIntrinsicCreate(int id, long eid) {
         validate();
         return rsnScriptIntrinsicCreate(mContext, id, eid);
     }
 
-    native int  rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
-    synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
+    native long  rsnScriptKernelIDCreate(long con, long sid, int slot, int sig);
+    synchronized long nScriptKernelIDCreate(long sid, int slot, int sig) {
         validate();
         return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
     }
 
-    native int  rsnScriptFieldIDCreate(int con, int sid, int slot);
-    synchronized int nScriptFieldIDCreate(int sid, int slot) {
+    native long  rsnScriptFieldIDCreate(long con, long sid, int slot);
+    synchronized long nScriptFieldIDCreate(long sid, int slot) {
         validate();
         return rsnScriptFieldIDCreate(mContext, sid, slot);
     }
 
-    native int  rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
-    synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
+    native long rsnScriptGroupCreate(long con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
+    synchronized long nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
         validate();
         return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
     }
 
-    native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
-    synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
+    native void rsnScriptGroupSetInput(long con, long group, long kernel, long alloc);
+    synchronized void nScriptGroupSetInput(long group, long kernel, long alloc) {
         validate();
         rsnScriptGroupSetInput(mContext, group, kernel, alloc);
     }
 
-    native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
-    synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
+    native void rsnScriptGroupSetOutput(long con, long group, long kernel, long alloc);
+    synchronized void nScriptGroupSetOutput(long group, long kernel, long alloc) {
         validate();
         rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
     }
 
-    native void rsnScriptGroupExecute(int con, int group);
-    synchronized void nScriptGroupExecute(int group) {
+    native void rsnScriptGroupExecute(long con, long group);
+    synchronized void nScriptGroupExecute(long group) {
         validate();
         rsnScriptGroupExecute(mContext, group);
     }
 
-    native int  rsnSamplerCreate(int con, int magFilter, int minFilter,
+    native long  rsnSamplerCreate(long con, int magFilter, int minFilter,
                                  int wrapS, int wrapT, int wrapR, float aniso);
-    synchronized int nSamplerCreate(int magFilter, int minFilter,
+    synchronized long nSamplerCreate(int magFilter, int minFilter,
                                  int wrapS, int wrapT, int wrapR, float aniso) {
         validate();
         return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
     }
 
-    native int  rsnProgramStoreCreate(int con, boolean r, boolean g, boolean b, boolean a,
+    native long rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
                                       boolean depthMask, boolean dither,
                                       int srcMode, int dstMode, int depthFunc);
-    synchronized int nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
+    synchronized long nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
                                          boolean depthMask, boolean dither,
                                          int srcMode, int dstMode, int depthFunc) {
         validate();
@@ -758,72 +747,72 @@
                                      dstMode, depthFunc);
     }
 
-    native int  rsnProgramRasterCreate(int con, boolean pointSprite, int cullMode);
-    synchronized int nProgramRasterCreate(boolean pointSprite, int cullMode) {
+    native long rsnProgramRasterCreate(long con, boolean pointSprite, int cullMode);
+    synchronized long nProgramRasterCreate(boolean pointSprite, int cullMode) {
         validate();
         return rsnProgramRasterCreate(mContext, pointSprite, cullMode);
     }
 
-    native void rsnProgramBindConstants(int con, int pv, int slot, int mID);
-    synchronized void nProgramBindConstants(int pv, int slot, int mID) {
+    native void rsnProgramBindConstants(long con, long pv, int slot, long mID);
+    synchronized void nProgramBindConstants(long pv, int slot, long mID) {
         validate();
         rsnProgramBindConstants(mContext, pv, slot, mID);
     }
-    native void rsnProgramBindTexture(int con, int vpf, int slot, int a);
-    synchronized void nProgramBindTexture(int vpf, int slot, int a) {
+    native void rsnProgramBindTexture(long con, long vpf, int slot, long a);
+    synchronized void nProgramBindTexture(long vpf, int slot, long a) {
         validate();
         rsnProgramBindTexture(mContext, vpf, slot, a);
     }
-    native void rsnProgramBindSampler(int con, int vpf, int slot, int s);
-    synchronized void nProgramBindSampler(int vpf, int slot, int s) {
+    native void rsnProgramBindSampler(long con, long vpf, int slot, long s);
+    synchronized void nProgramBindSampler(long vpf, int slot, long s) {
         validate();
         rsnProgramBindSampler(mContext, vpf, slot, s);
     }
-    native int  rsnProgramFragmentCreate(int con, String shader, String[] texNames, int[] params);
-    synchronized int nProgramFragmentCreate(String shader, String[] texNames, int[] params) {
+    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, int[] params);
+    synchronized long nProgramFragmentCreate(String shader, String[] texNames, int[] params) {
         validate();
         return rsnProgramFragmentCreate(mContext, shader, texNames, params);
     }
-    native int  rsnProgramVertexCreate(int con, String shader, String[] texNames, int[] params);
-    synchronized int nProgramVertexCreate(String shader, String[] texNames, int[] params) {
+    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, int[] params);
+    synchronized long nProgramVertexCreate(String shader, String[] texNames, int[] params) {
         validate();
         return rsnProgramVertexCreate(mContext, shader, texNames, params);
     }
 
-    native int  rsnMeshCreate(int con, int[] vtx, int[] idx, int[] prim);
-    synchronized int nMeshCreate(int[] vtx, int[] idx, int[] prim) {
+    native long rsnMeshCreate(long con, int[] vtx, int[] idx, int[] prim);
+    synchronized long nMeshCreate(int[] vtx, int[] idx, int[] prim) {
         validate();
         return rsnMeshCreate(mContext, vtx, idx, prim);
     }
-    native int  rsnMeshGetVertexBufferCount(int con, int id);
-    synchronized int nMeshGetVertexBufferCount(int id) {
+    native int  rsnMeshGetVertexBufferCount(long con, long id);
+    synchronized int nMeshGetVertexBufferCount(long id) {
         validate();
         return rsnMeshGetVertexBufferCount(mContext, id);
     }
-    native int  rsnMeshGetIndexCount(int con, int id);
-    synchronized int nMeshGetIndexCount(int id) {
+    native int  rsnMeshGetIndexCount(long con, long id);
+    synchronized int nMeshGetIndexCount(long id) {
         validate();
         return rsnMeshGetIndexCount(mContext, id);
     }
-    native void rsnMeshGetVertices(int con, int id, int[] vtxIds, int vtxIdCount);
-    synchronized void nMeshGetVertices(int id, int[] vtxIds, int vtxIdCount) {
+    native void rsnMeshGetVertices(long con, long id, int[] vtxIds, int vtxIdCount);
+    synchronized void nMeshGetVertices(long id, int[] vtxIds, int vtxIdCount) {
         validate();
         rsnMeshGetVertices(mContext, id, vtxIds, vtxIdCount);
     }
-    native void rsnMeshGetIndices(int con, int id, int[] idxIds, int[] primitives, int vtxIdCount);
-    synchronized void nMeshGetIndices(int id, int[] idxIds, int[] primitives, int vtxIdCount) {
+    native void rsnMeshGetIndices(long con, long id, int[] idxIds, int[] primitives, int vtxIdCount);
+    synchronized void nMeshGetIndices(long id, int[] idxIds, int[] primitives, int vtxIdCount) {
         validate();
         rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
     }
 
-    native int  rsnPathCreate(int con, int prim, boolean isStatic, int vtx, int loop, float q);
-    synchronized int nPathCreate(int prim, boolean isStatic, int vtx, int loop, float q) {
+    native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, long loop, float q);
+    synchronized long nPathCreate(int prim, boolean isStatic, long vtx, long loop, float q) {
         validate();
         return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q);
     }
 
-    int     mDev;
-    int     mContext;
+    long     mDev;
+    long     mContext;
     @SuppressWarnings({"FieldCanBeLocal"})
     MessageThread mMessageThread;
 
@@ -1136,6 +1125,7 @@
         if (ctx != null) {
             mApplicationContext = ctx.getApplicationContext();
         }
+        mRWLock = new ReentrantReadWriteLock();
     }
 
     /**
@@ -1230,6 +1220,8 @@
      */
     public void destroy() {
         validate();
+        nContextFinish();
+
         nContextDeinitToClient(mContext);
         mMessageThread.mRun = false;
         try {
@@ -1238,7 +1230,6 @@
         }
 
         nContextDestroy();
-        mContext = 0;
 
         nDeviceDestroy(mDev);
         mDev = 0;
@@ -1248,7 +1239,7 @@
         return mContext != 0;
     }
 
-    int safeID(BaseObj o) {
+    long safeID(BaseObj o) {
         if(o != null) {
             return o.getID(this);
         }
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
similarity index 97%
rename from graphics/java/android/renderscript/RenderScriptGL.java
rename to rs/java/android/renderscript/RenderScriptGL.java
index bac9c68..c9cbe3e 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -286,7 +286,7 @@
      */
     public void bindRootScript(Script s) {
         validate();
-        nContextBindRootScript(safeID(s));
+        nContextBindRootScript((int)safeID(s));
     }
 
     /**
@@ -298,7 +298,7 @@
      */
     public void bindProgramStore(ProgramStore p) {
         validate();
-        nContextBindProgramStore(safeID(p));
+        nContextBindProgramStore((int)safeID(p));
     }
 
     /**
@@ -310,7 +310,7 @@
      */
     public void bindProgramFragment(ProgramFragment p) {
         validate();
-        nContextBindProgramFragment(safeID(p));
+        nContextBindProgramFragment((int)safeID(p));
     }
 
     /**
@@ -322,7 +322,7 @@
      */
     public void bindProgramRaster(ProgramRaster p) {
         validate();
-        nContextBindProgramRaster(safeID(p));
+        nContextBindProgramRaster((int)safeID(p));
     }
 
     /**
@@ -334,7 +334,7 @@
      */
     public void bindProgramVertex(ProgramVertex p) {
         validate();
-        nContextBindProgramVertex(safeID(p));
+        nContextBindProgramVertex((int)safeID(p));
     }
 
 }
diff --git a/graphics/java/android/renderscript/Sampler.java b/rs/java/android/renderscript/Sampler.java
similarity index 98%
rename from graphics/java/android/renderscript/Sampler.java
rename to rs/java/android/renderscript/Sampler.java
index 623055fe..8d0e29e 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/rs/java/android/renderscript/Sampler.java
@@ -60,7 +60,7 @@
     Value mWrapR;
     float mAniso;
 
-    Sampler(int id, RenderScript rs) {
+    Sampler(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -347,7 +347,7 @@
 
         public Sampler create() {
             mRS.validate();
-            int id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
+            long id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
                                         mWrapS.mID, mWrapT.mID, mWrapR.mID, mAniso);
             Sampler sampler = new Sampler(id, mRS);
             sampler.mMin = mMin;
diff --git a/graphics/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
similarity index 93%
rename from graphics/java/android/renderscript/Script.java
rename to rs/java/android/renderscript/Script.java
index 0026e0e..a1f2287 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -36,7 +36,7 @@
         Script mScript;
         int mSlot;
         int mSig;
-        KernelID(int id, RenderScript rs, Script s, int slot, int sig) {
+        KernelID(long id, RenderScript rs, Script s, int slot, int sig) {
             super(id, rs);
             mScript = s;
             mSlot = slot;
@@ -54,7 +54,7 @@
             return k;
         }
 
-        int id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
+        long id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
         if (id == 0) {
             throw new RSDriverException("Failed to create KernelID");
         }
@@ -75,7 +75,7 @@
     public static final class FieldID extends BaseObj {
         Script mScript;
         int mSlot;
-        FieldID(int id, RenderScript rs, Script s, int slot) {
+        FieldID(long id, RenderScript rs, Script s, int slot) {
             super(id, rs);
             mScript = s;
             mSlot = slot;
@@ -92,7 +92,7 @@
             return f;
         }
 
-        int id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
+        long id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
         if (id == 0) {
             throw new RSDriverException("Failed to create FieldID");
         }
@@ -132,11 +132,11 @@
             throw new RSIllegalArgumentException(
                 "At least one of ain or aout is required to be non-null.");
         }
-        int in_id = 0;
+        long in_id = 0;
         if (ain != null) {
             in_id = ain.getID(mRS);
         }
-        int out_id = 0;
+        long out_id = 0;
         if (aout != null) {
             out_id = aout.getID(mRS);
         }
@@ -161,11 +161,11 @@
             forEach(slot, ain, aout, v);
             return;
         }
-        int in_id = 0;
+        long in_id = 0;
         if (ain != null) {
             in_id = ain.getID(mRS);
         }
-        int out_id = 0;
+        long out_id = 0;
         if (aout != null) {
             out_id = aout.getID(mRS);
         }
@@ -176,7 +176,7 @@
         mRS.nScriptForEachClipped(getID(mRS), slot, in_id, out_id, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend);
     }
 
-    Script(int id, RenderScript rs) {
+    Script(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -188,6 +188,13 @@
     public void bindAllocation(Allocation va, int slot) {
         mRS.validate();
         if (va != null) {
+            if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 20) {
+                final Type t = va.mType;
+                if (t.hasMipmaps() || t.hasFaces() || (t.getY() != 0) || (t.getZ() != 0)) {
+                    throw new RSIllegalArgumentException(
+                        "API 20+ only allows simple 1D allocations to be used with bind.");
+                }
+            }
             mRS.nScriptBindAllocation(getID(mRS), va.getID(mRS), slot);
         } else {
             mRS.nScriptBindAllocation(getID(mRS), 0, slot);
diff --git a/graphics/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
similarity index 89%
rename from graphics/java/android/renderscript/ScriptC.java
rename to rs/java/android/renderscript/ScriptC.java
index b0a5759..cdb2b08 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -45,7 +45,17 @@
     protected ScriptC(int id, RenderScript rs) {
         super(id, rs);
     }
-
+    /**
+     * Only intended for use by the generated derived classes.
+     *
+     * @param id
+     * @param rs
+     *
+     * @hide
+     */
+    protected ScriptC(long id, RenderScript rs) {
+        super(id, rs);
+    }
     /**
      * Only intended for use by the generated derived classes.
      *
@@ -56,7 +66,7 @@
      */
     protected ScriptC(RenderScript rs, Resources resources, int resourceID) {
         super(0, rs);
-        int id = internalCreate(rs, resources, resourceID);
+        long id = internalCreate(rs, resources, resourceID);
         if (id == 0) {
             throw new RSRuntimeException("Loading of ScriptC script failed.");
         }
@@ -70,7 +80,7 @@
 
     static String mCachePath;
 
-    private static synchronized int internalCreate(RenderScript rs, Resources resources, int resourceID) {
+    private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
         byte[] pgm;
         int pgmLength;
         InputStream is = resources.openRawResource(resourceID);
diff --git a/graphics/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
similarity index 96%
rename from graphics/java/android/renderscript/ScriptGroup.java
rename to rs/java/android/renderscript/ScriptGroup.java
index 1416641..48dba30 100644
--- a/graphics/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -89,7 +89,7 @@
     }
 
 
-    ScriptGroup(int id, RenderScript rs) {
+    ScriptGroup(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -380,6 +380,7 @@
          * @return ScriptGroup The new ScriptGroup
          */
         public ScriptGroup create() {
+            // FIXME: this is broken for 64-bit
 
             if (mNodes.size() == 0) {
                 throw new RSInvalidStateException("Empty script groups are not allowed");
@@ -400,7 +401,7 @@
                 Node n = mNodes.get(ct);
                 for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
                     final Script.KernelID kid = n.mKernels.get(ct2);
-                    kernels[idx++] = kid.getID(mRS);
+                    kernels[idx++] = (int)kid.getID(mRS);
 
                     boolean hasInput = false;
                     boolean hasOutput = false;
@@ -434,17 +435,17 @@
 
             for (int ct=0; ct < mLines.size(); ct++) {
                 ConnectLine cl = mLines.get(ct);
-                src[ct] = cl.mFrom.getID(mRS);
+                src[ct] = (int)cl.mFrom.getID(mRS);
                 if (cl.mToK != null) {
-                    dstk[ct] = cl.mToK.getID(mRS);
+                    dstk[ct] = (int)cl.mToK.getID(mRS);
                 }
                 if (cl.mToF != null) {
-                    dstf[ct] = cl.mToF.getID(mRS);
+                    dstf[ct] = (int)cl.mToF.getID(mRS);
                 }
-                types[ct] = cl.mAllocationType.getID(mRS);
+                types[ct] = (int)cl.mAllocationType.getID(mRS);
             }
 
-            int id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
+            long id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
             if (id == 0) {
                 throw new RSRuntimeException("Object creation error, should not happen.");
             }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic.java b/rs/java/android/renderscript/ScriptIntrinsic.java
similarity index 95%
rename from graphics/java/android/renderscript/ScriptIntrinsic.java
rename to rs/java/android/renderscript/ScriptIntrinsic.java
index 096268a..8719e017 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsic.java
+++ b/rs/java/android/renderscript/ScriptIntrinsic.java
@@ -25,7 +25,7 @@
  * Not intended for direct use.
  **/
 public abstract class ScriptIntrinsic extends Script {
-    ScriptIntrinsic(int id, RenderScript rs) {
+    ScriptIntrinsic(long id, RenderScript rs) {
         super(id, rs);
     }
 }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java b/rs/java/android/renderscript/ScriptIntrinsic3DLUT.java
similarity index 95%
rename from graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
rename to rs/java/android/renderscript/ScriptIntrinsic3DLUT.java
index 34540a1..96ec875 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
+++ b/rs/java/android/renderscript/ScriptIntrinsic3DLUT.java
@@ -30,7 +30,7 @@
     private Allocation mLUT;
     private Element mElement;
 
-    private ScriptIntrinsic3DLUT(int id, RenderScript rs, Element e) {
+    private ScriptIntrinsic3DLUT(long id, RenderScript rs, Element e) {
         super(id, rs);
         mElement = e;
     }
@@ -46,7 +46,7 @@
      * @return ScriptIntrinsic3DLUT
      */
     public static ScriptIntrinsic3DLUT create(RenderScript rs, Element e) {
-        int id = rs.nScriptIntrinsicCreate(8, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(8, e.getID(rs));
 
         if (!e.isCompatible(Element.U8_4(rs))) {
             throw new RSIllegalArgumentException("Element must be compatible with uchar4.");
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlend.java b/rs/java/android/renderscript/ScriptIntrinsicBlend.java
similarity index 98%
rename from graphics/java/android/renderscript/ScriptIntrinsicBlend.java
rename to rs/java/android/renderscript/ScriptIntrinsicBlend.java
index 0e05bc8..40f1a3e 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicBlend.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBlend.java
@@ -21,7 +21,7 @@
  * Intrinsic kernels for blending two {@link android.renderscript.Allocation} objects.
  **/
 public class ScriptIntrinsicBlend extends ScriptIntrinsic {
-    ScriptIntrinsicBlend(int id, RenderScript rs) {
+    ScriptIntrinsicBlend(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -35,7 +35,7 @@
      */
     public static ScriptIntrinsicBlend create(RenderScript rs, Element e) {
         // 7 comes from RS_SCRIPT_INTRINSIC_ID_BLEND in rsDefines.h
-        int id = rs.nScriptIntrinsicCreate(7, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(7, e.getID(rs));
         return new ScriptIntrinsicBlend(id, rs);
 
     }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
similarity index 95%
rename from graphics/java/android/renderscript/ScriptIntrinsicBlur.java
rename to rs/java/android/renderscript/ScriptIntrinsicBlur.java
index aaf5ffc..d1a6fed 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -30,7 +30,7 @@
     private final float[] mValues = new float[9];
     private Allocation mInput;
 
-    private ScriptIntrinsicBlur(int id, RenderScript rs) {
+    private ScriptIntrinsicBlur(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -49,7 +49,7 @@
         if ((!e.isCompatible(Element.U8_4(rs))) && (!e.isCompatible(Element.U8(rs)))) {
             throw new RSIllegalArgumentException("Unsuported element type.");
         }
-        int id = rs.nScriptIntrinsicCreate(5, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(5, e.getID(rs));
         ScriptIntrinsicBlur sib = new ScriptIntrinsicBlur(id, rs);
         sib.setRadius(5.f);
         return sib;
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/rs/java/android/renderscript/ScriptIntrinsicColorMatrix.java
similarity index 98%
rename from graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
rename to rs/java/android/renderscript/ScriptIntrinsicColorMatrix.java
index 32c3d15..601db17 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -43,7 +43,7 @@
     private final Matrix4f mMatrix = new Matrix4f();
     private final Float4 mAdd = new Float4();
 
-    private ScriptIntrinsicColorMatrix(int id, RenderScript rs) {
+    private ScriptIntrinsicColorMatrix(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -75,7 +75,7 @@
      * @return ScriptIntrinsicColorMatrix
      */
     public static ScriptIntrinsicColorMatrix create(RenderScript rs) {
-        int id = rs.nScriptIntrinsicCreate(2, 0);
+        long id = rs.nScriptIntrinsicCreate(2, 0);
         return new ScriptIntrinsicColorMatrix(id, rs);
 
     }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
similarity index 96%
rename from graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
rename to rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
index 5d3c1d3..25f3ee8 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -26,7 +26,7 @@
     private final float[] mValues = new float[9];
     private Allocation mInput;
 
-    private ScriptIntrinsicConvolve3x3(int id, RenderScript rs) {
+    private ScriptIntrinsicConvolve3x3(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -61,7 +61,7 @@
             !e.isCompatible(Element.F32_4(rs))) {
             throw new RSIllegalArgumentException("Unsuported element type.");
         }
-        int id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
         ScriptIntrinsicConvolve3x3 si = new ScriptIntrinsicConvolve3x3(id, rs);
         si.setCoefficients(f);
         return si;
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
similarity index 96%
rename from graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
rename to rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
index ad09f95..71ea4cbc 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -26,7 +26,7 @@
     private final float[] mValues = new float[25];
     private Allocation mInput;
 
-    private ScriptIntrinsicConvolve5x5(int id, RenderScript rs) {
+    private ScriptIntrinsicConvolve5x5(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -62,7 +62,7 @@
             throw new RSIllegalArgumentException("Unsuported element type.");
         }
 
-        int id = rs.nScriptIntrinsicCreate(4, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(4, e.getID(rs));
         return new ScriptIntrinsicConvolve5x5(id, rs);
 
     }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicHistogram.java b/rs/java/android/renderscript/ScriptIntrinsicHistogram.java
similarity index 97%
rename from graphics/java/android/renderscript/ScriptIntrinsicHistogram.java
rename to rs/java/android/renderscript/ScriptIntrinsicHistogram.java
index adc2d95..42e4d04 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicHistogram.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicHistogram.java
@@ -28,7 +28,7 @@
 public final class ScriptIntrinsicHistogram extends ScriptIntrinsic {
     private Allocation mOut;
 
-    private ScriptIntrinsicHistogram(int id, RenderScript rs) {
+    private ScriptIntrinsicHistogram(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -52,7 +52,7 @@
             (!e.isCompatible(Element.U8(rs)))) {
             throw new RSIllegalArgumentException("Unsuported element type.");
         }
-        int id = rs.nScriptIntrinsicCreate(9, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(9, e.getID(rs));
         ScriptIntrinsicHistogram sib = new ScriptIntrinsicHistogram(id, rs);
         return sib;
     }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java b/rs/java/android/renderscript/ScriptIntrinsicLUT.java
similarity index 96%
rename from graphics/java/android/renderscript/ScriptIntrinsicLUT.java
rename to rs/java/android/renderscript/ScriptIntrinsicLUT.java
index 0f7ab38..c45c015 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicLUT.java
@@ -30,7 +30,7 @@
     private final byte mCache[] = new byte[1024];
     private boolean mDirty = true;
 
-    private ScriptIntrinsicLUT(int id, RenderScript rs) {
+    private ScriptIntrinsicLUT(long id, RenderScript rs) {
         super(id, rs);
         mTables = Allocation.createSized(rs, Element.U8(rs), 1024);
         for (int ct=0; ct < 256; ct++) {
@@ -53,7 +53,7 @@
      * @return ScriptIntrinsicLUT
      */
     public static ScriptIntrinsicLUT create(RenderScript rs, Element e) {
-        int id = rs.nScriptIntrinsicCreate(3, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(3, e.getID(rs));
         return new ScriptIntrinsicLUT(id, rs);
 
     }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
similarity index 95%
rename from graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
rename to rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
index 845625d..f942982 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -27,7 +27,7 @@
 public final class ScriptIntrinsicYuvToRGB extends ScriptIntrinsic {
     private Allocation mInput;
 
-    ScriptIntrinsicYuvToRGB(int id, RenderScript rs) {
+    ScriptIntrinsicYuvToRGB(long id, RenderScript rs) {
         super(id, rs);
     }
 
@@ -43,7 +43,7 @@
      */
     public static ScriptIntrinsicYuvToRGB create(RenderScript rs, Element e) {
         // 6 comes from RS_SCRIPT_INTRINSIC_YUV_TO_RGB in rsDefines.h
-        int id = rs.nScriptIntrinsicCreate(6, e.getID(rs));
+        long id = rs.nScriptIntrinsicCreate(6, e.getID(rs));
         ScriptIntrinsicYuvToRGB si = new ScriptIntrinsicYuvToRGB(id, rs);
         return si;
     }
diff --git a/graphics/java/android/renderscript/Short2.java b/rs/java/android/renderscript/Short2.java
similarity index 100%
rename from graphics/java/android/renderscript/Short2.java
rename to rs/java/android/renderscript/Short2.java
diff --git a/graphics/java/android/renderscript/Short3.java b/rs/java/android/renderscript/Short3.java
similarity index 100%
rename from graphics/java/android/renderscript/Short3.java
rename to rs/java/android/renderscript/Short3.java
diff --git a/graphics/java/android/renderscript/Short4.java b/rs/java/android/renderscript/Short4.java
similarity index 100%
rename from graphics/java/android/renderscript/Short4.java
rename to rs/java/android/renderscript/Short4.java
diff --git a/graphics/java/android/renderscript/Type.java b/rs/java/android/renderscript/Type.java
similarity index 78%
rename from graphics/java/android/renderscript/Type.java
rename to rs/java/android/renderscript/Type.java
index e023739..7283814 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/rs/java/android/renderscript/Type.java
@@ -190,16 +190,18 @@
     }
 
 
-    Type(int id, RenderScript rs) {
+    Type(long id, RenderScript rs) {
         super(id, rs);
     }
 
     @Override
     void updateFromNative() {
+        // FIXME: rsaTypeGetNativeData needs 32-bit and 64-bit paths
+
         // We have 6 integer to obtain mDimX; mDimY; mDimZ;
         // mDimLOD; mDimFaces; mElement;
         int[] dataBuffer = new int[6];
-        mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
+        mRS.nTypeGetNativeData((int)getID(mRS), dataBuffer);
 
         mDimX = dataBuffer[0];
         mDimY = dataBuffer[1];
@@ -216,6 +218,81 @@
     }
 
     /**
+     * Utility function for creating basic 1D types. The type is
+     * created without mipmaps enabled.
+     *
+     * @param rs The RenderScript context
+     * @param e The Element for the Type
+     * @param dimX The X dimension, must be > 0
+     *
+     * @return Type
+     */
+    static public Type createX(RenderScript rs, Element e, int dimX) {
+        if (dimX < 1) {
+            throw new RSInvalidStateException("Dimension must be >= 1.");
+        }
+
+        long id = rs.nTypeCreate(e.getID(rs), dimX, 0, 0, false, false, 0);
+        Type t = new Type(id, rs);
+        t.mElement = e;
+        t.mDimX = dimX;
+        t.calcElementCount();
+        return t;
+    }
+
+    /**
+     * Utility function for creating basic 2D types. The type is
+     * created without mipmaps or cubemaps.
+     *
+     * @param rs The RenderScript context
+     * @param e The Element for the Type
+     * @param dimX The X dimension, must be > 0
+     * @param dimY The Y dimension, must be > 0
+     *
+     * @return Type
+     */
+    static public Type createXY(RenderScript rs, Element e, int dimX, int dimY) {
+        if ((dimX < 1) || (dimY < 1)) {
+            throw new RSInvalidStateException("Dimension must be >= 1.");
+        }
+
+        long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, 0, false, false, 0);
+        Type t = new Type(id, rs);
+        t.mElement = e;
+        t.mDimX = dimX;
+        t.mDimY = dimY;
+        t.calcElementCount();
+        return t;
+    }
+
+    /**
+     * Utility function for creating basic 3D types. The type is
+     * created without mipmaps.
+     *
+     * @param rs The RenderScript context
+     * @param e The Element for the Type
+     * @param dimX The X dimension, must be > 0
+     * @param dimY The Y dimension, must be > 0
+     * @param dimZ The Z dimension, must be > 0
+     *
+     * @return Type
+     */
+    static public Type createXYZ(RenderScript rs, Element e, int dimX, int dimY, int dimZ) {
+        if ((dimX < 1) || (dimY < 1) || (dimZ < 1)) {
+            throw new RSInvalidStateException("Dimension must be >= 1.");
+        }
+
+        long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, dimZ, false, false, 0);
+        Type t = new Type(id, rs);
+        t.mElement = e;
+        t.mDimX = dimX;
+        t.mDimY = dimY;
+        t.mDimZ = dimZ;
+        t.calcElementCount();
+        return t;
+    }
+
+    /**
      * Builder class for Type.
      *
      */
@@ -336,7 +413,7 @@
                 }
             }
 
-            int id = mRS.nTypeCreate(mElement.getID(mRS),
+            long id = mRS.nTypeCreate(mElement.getID(mRS),
                                      mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces, mYuv);
             Type t = new Type(id, mRS);
             t.mElement = mElement;
diff --git a/graphics/java/android/renderscript/package.html b/rs/java/android/renderscript/package.html
similarity index 100%
rename from graphics/java/android/renderscript/package.html
rename to rs/java/android/renderscript/package.html
diff --git a/graphics/jni/Android.mk b/rs/jni/Android.mk
similarity index 95%
rename from graphics/jni/Android.mk
rename to rs/jni/Android.mk
index e8beae53..cbb5b3b 100644
--- a/graphics/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -26,7 +26,7 @@
 	$(rs_generated_include_dir) \
 	$(call include-path-for, corecg graphics)
 
-LOCAL_CFLAGS +=
+LOCAL_CFLAGS += -Wno-unused-parameter
 
 LOCAL_LDLIBS := -lpthread
 LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
new file mode 100644
index 0000000..c4e19a1
--- /dev/null
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -0,0 +1,1659 @@
+/*
+ * Copyright (C) 2011-2012 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.
+ */
+
+#define LOG_TAG "libRS_jni"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <math.h>
+#include <utils/misc.h>
+
+#include <core/SkBitmap.h>
+#include <core/SkPixelRef.h>
+#include <core/SkStream.h>
+#include <core/SkTemplates.h>
+
+#include <androidfw/Asset.h>
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_view_Surface.h"
+#include "android_runtime/android_util_AssetManager.h"
+
+#include <rs.h>
+#include <rsEnv.h>
+#include <gui/Surface.h>
+#include <gui/GLConsumer.h>
+#include <gui/Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
+
+//#define LOG_API ALOGE
+#define LOG_API(...)
+
+using namespace android;
+
+#define PER_ARRAY_TYPE(flag, fnc, ...) {                                                \
+    jint len = 0;                                                                       \
+    void *ptr = NULL;                                                                   \
+    size_t typeBytes = 0;                                                               \
+    switch(dataType) {                                                                  \
+    case RS_TYPE_FLOAT_32:                                                              \
+        len = _env->GetArrayLength((jfloatArray)data);                                  \
+        ptr = _env->GetFloatArrayElements((jfloatArray)data, flag);                     \
+        typeBytes = 4;                                                                  \
+        fnc(__VA_ARGS__);                                                               \
+        _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, JNI_ABORT);   \
+        return;                                                                         \
+    case RS_TYPE_FLOAT_64:                                                              \
+        len = _env->GetArrayLength((jdoubleArray)data);                                 \
+        ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag);                   \
+        typeBytes = 8;                                                                  \
+        fnc(__VA_ARGS__);                                                               \
+        _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, JNI_ABORT);\
+        return;                                                                         \
+    case RS_TYPE_SIGNED_8:                                                              \
+    case RS_TYPE_UNSIGNED_8:                                                            \
+        len = _env->GetArrayLength((jbyteArray)data);                                   \
+        ptr = _env->GetByteArrayElements((jbyteArray)data, flag);                       \
+        typeBytes = 1;                                                                  \
+        fnc(__VA_ARGS__);                                                               \
+        _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, JNI_ABORT);       \
+        return;                                                                         \
+    case RS_TYPE_SIGNED_16:                                                             \
+    case RS_TYPE_UNSIGNED_16:                                                           \
+        len = _env->GetArrayLength((jshortArray)data);                                  \
+        ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
+        typeBytes = 2;                                                                  \
+        fnc(__VA_ARGS__);                                                               \
+        _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, JNI_ABORT);   \
+        return;                                                                         \
+    case RS_TYPE_SIGNED_32:                                                             \
+    case RS_TYPE_UNSIGNED_32:                                                           \
+        len = _env->GetArrayLength((jintArray)data);                                    \
+        ptr = _env->GetIntArrayElements((jintArray)data, flag);                         \
+        typeBytes = 4;                                                                  \
+        fnc(__VA_ARGS__);                                                               \
+        _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, JNI_ABORT);         \
+        return;                                                                         \
+    case RS_TYPE_SIGNED_64:                                                             \
+    case RS_TYPE_UNSIGNED_64:                                                           \
+        len = _env->GetArrayLength((jlongArray)data);                                   \
+        ptr = _env->GetLongArrayElements((jlongArray)data, flag);                       \
+        typeBytes = 8;                                                                  \
+        fnc(__VA_ARGS__);                                                               \
+        _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, JNI_ABORT);      \
+        return;                                                                         \
+    default:                                                                            \
+        break;                                                                          \
+    }                                                                                   \
+}
+
+
+class AutoJavaStringToUTF8 {
+public:
+    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
+        fCStr = env->GetStringUTFChars(str, NULL);
+        fLength = env->GetStringUTFLength(str);
+    }
+    ~AutoJavaStringToUTF8() {
+        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
+    }
+    const char* c_str() const { return fCStr; }
+    jsize length() const { return fLength; }
+
+private:
+    JNIEnv*     fEnv;
+    jstring     fJStr;
+    const char* fCStr;
+    jsize       fLength;
+};
+
+class AutoJavaStringArrayToUTF8 {
+public:
+    AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength)
+    : mEnv(env), mStrings(strings), mStringsLength(stringsLength) {
+        mCStrings = NULL;
+        mSizeArray = NULL;
+        if (stringsLength > 0) {
+            mCStrings = (const char **)calloc(stringsLength, sizeof(char *));
+            mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t));
+            for (jsize ct = 0; ct < stringsLength; ct ++) {
+                jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
+                mCStrings[ct] = mEnv->GetStringUTFChars(s, NULL);
+                mSizeArray[ct] = mEnv->GetStringUTFLength(s);
+            }
+        }
+    }
+    ~AutoJavaStringArrayToUTF8() {
+        for (jsize ct=0; ct < mStringsLength; ct++) {
+            jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
+            mEnv->ReleaseStringUTFChars(s, mCStrings[ct]);
+        }
+        free(mCStrings);
+        free(mSizeArray);
+    }
+    const char **c_str() const { return mCStrings; }
+    size_t *c_str_len() const { return mSizeArray; }
+    jsize length() const { return mStringsLength; }
+
+private:
+    JNIEnv      *mEnv;
+    jobjectArray mStrings;
+    const char **mCStrings;
+    size_t      *mSizeArray;
+    jsize        mStringsLength;
+};
+
+// ---------------------------------------------------------------------------
+
+static jfieldID gContextId = 0;
+static jfieldID gNativeBitmapID = 0;
+static jfieldID gTypeNativeCache = 0;
+
+static void _nInit(JNIEnv *_env, jclass _this)
+{
+    gContextId             = _env->GetFieldID(_this, "mContext", "J");
+
+    jclass bitmapClass = _env->FindClass("android/graphics/Bitmap");
+    gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "J");
+}
+
+// ---------------------------------------------------------------------------
+
+static void
+nContextFinish(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextFinish, con(%p)", (RsContext)con);
+    rsContextFinish((RsContext)con);
+}
+
+static void
+nAssignName(JNIEnv *_env, jobject _this, jlong con, jlong obj, jbyteArray str)
+{
+    LOG_API("nAssignName, con(%p), obj(%p)", (RsContext)con, (void *)obj);
+    jint len = _env->GetArrayLength(str);
+    jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
+    rsAssignName((RsContext)con, (void *)obj, (const char *)cptr, len);
+    _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
+}
+
+static jstring
+nGetName(JNIEnv *_env, jobject _this, jlong con, jlong obj)
+{
+    LOG_API("nGetName, con(%p), obj(%p)", (RsContext)con, (void *)obj);
+    const char *name = NULL;
+    rsaGetName((RsContext)con, (void *)obj, &name);
+    if(name == NULL || strlen(name) == 0) {
+        return NULL;
+    }
+    return _env->NewStringUTF(name);
+}
+
+static void
+nObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj)
+{
+    LOG_API("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj);
+    rsObjDestroy((RsContext)con, (void *)obj);
+}
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nDeviceCreate(JNIEnv *_env, jobject _this)
+{
+    LOG_API("nDeviceCreate");
+    return (jlong)rsDeviceCreate();
+}
+
+static void
+nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev)
+{
+    LOG_API("nDeviceDestroy");
+    return rsDeviceDestroy((RsDevice)dev);
+}
+
+static void
+nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value)
+{
+    LOG_API("nDeviceSetConfig  dev(%p), param(%i), value(%i)", (void *)dev, p, value);
+    return rsDeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value);
+}
+
+static jlong
+nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
+{
+    LOG_API("nContextCreate");
+    return (jlong)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
+}
+
+static jlong
+nContextCreateGL(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
+                 jint colorMin, jint colorPref,
+                 jint alphaMin, jint alphaPref,
+                 jint depthMin, jint depthPref,
+                 jint stencilMin, jint stencilPref,
+                 jint samplesMin, jint samplesPref, jfloat samplesQ,
+                 jint dpi)
+{
+    RsSurfaceConfig sc;
+    sc.alphaMin = alphaMin;
+    sc.alphaPref = alphaPref;
+    sc.colorMin = colorMin;
+    sc.colorPref = colorPref;
+    sc.depthMin = depthMin;
+    sc.depthPref = depthPref;
+    sc.samplesMin = samplesMin;
+    sc.samplesPref = samplesPref;
+    sc.samplesQ = samplesQ;
+
+    LOG_API("nContextCreateGL");
+    return (jlong)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
+}
+
+static void
+nContextSetPriority(JNIEnv *_env, jobject _this, jlong con, jint p)
+{
+    LOG_API("ContextSetPriority, con(%p), priority(%i)", (RsContext)con, p);
+    rsContextSetPriority((RsContext)con, p);
+}
+
+
+
+static void
+nContextSetSurface(JNIEnv *_env, jobject _this, jlong con, jint width, jint height, jobject wnd)
+{
+    LOG_API("nContextSetSurface, con(%p), width(%i), height(%i), surface(%p)", (RsContext)con, width, height, (Surface *)wnd);
+
+    ANativeWindow * window = NULL;
+    if (wnd == NULL) {
+
+    } else {
+        window = android_view_Surface_getNativeWindow(_env, wnd).get();
+    }
+
+    rsContextSetSurface((RsContext)con, width, height, window);
+}
+
+static void
+nContextDestroy(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
+    rsContextDestroy((RsContext)con);
+}
+
+static void
+nContextDump(JNIEnv *_env, jobject _this, jlong con, jint bits)
+{
+    LOG_API("nContextDump, con(%p)  bits(%i)", (RsContext)con, bits);
+    rsContextDump((RsContext)con, bits);
+}
+
+static void
+nContextPause(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextPause, con(%p)", (RsContext)con);
+    rsContextPause((RsContext)con);
+}
+
+static void
+nContextResume(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextResume, con(%p)", (RsContext)con);
+    rsContextResume((RsContext)con);
+}
+
+
+static jstring
+nContextGetErrorMessage(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextGetErrorMessage, con(%p)", (RsContext)con);
+    char buf[1024];
+
+    size_t receiveLen;
+    uint32_t subID;
+    int id = rsContextGetMessage((RsContext)con,
+                                 buf, sizeof(buf),
+                                 &receiveLen, sizeof(receiveLen),
+                                 &subID, sizeof(subID));
+    if (!id && receiveLen) {
+        ALOGV("message receive buffer too small.  %i", receiveLen);
+    }
+    return _env->NewStringUTF(buf);
+}
+
+static jint
+nContextGetUserMessage(JNIEnv *_env, jobject _this, jlong con, jintArray data)
+{
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nContextGetMessage, con(%p), len(%i)", (RsContext)con, len);
+    jint *ptr = _env->GetIntArrayElements(data, NULL);
+    size_t receiveLen;
+    uint32_t subID;
+    int id = rsContextGetMessage((RsContext)con,
+                                 ptr, len * 4,
+                                 &receiveLen, sizeof(receiveLen),
+                                 &subID, sizeof(subID));
+    if (!id && receiveLen) {
+        ALOGV("message receive buffer too small.  %i", receiveLen);
+    }
+    _env->ReleaseIntArrayElements(data, ptr, 0);
+    return (jint)id;
+}
+
+static jint
+nContextPeekMessage(JNIEnv *_env, jobject _this, jlong con, jintArray auxData)
+{
+    LOG_API("nContextPeekMessage, con(%p)", (RsContext)con);
+    jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
+    size_t receiveLen;
+    uint32_t subID;
+    int id = rsContextPeekMessage((RsContext)con, &receiveLen, sizeof(receiveLen),
+                                  &subID, sizeof(subID));
+    auxDataPtr[0] = (jint)subID;
+    auxDataPtr[1] = (jint)receiveLen;
+    _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
+    return (jint)id;
+}
+
+static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextInitToClient, con(%p)", (RsContext)con);
+    rsContextInitToClient((RsContext)con);
+}
+
+static void nContextDeinitToClient(JNIEnv *_env, jobject _this, jlong con)
+{
+    LOG_API("nContextDeinitToClient, con(%p)", (RsContext)con);
+    rsContextDeinitToClient((RsContext)con);
+}
+
+static void
+nContextSendMessage(JNIEnv *_env, jobject _this, jlong con, jint id, jintArray data)
+{
+    jint *ptr = NULL;
+    jint len = 0;
+    if (data) {
+        len = _env->GetArrayLength(data);
+        jint *ptr = _env->GetIntArrayElements(data, NULL);
+    }
+    LOG_API("nContextSendMessage, con(%p), id(%i), len(%i)", (RsContext)con, id, len);
+    rsContextSendMessage((RsContext)con, id, (const uint8_t *)ptr, len * sizeof(int));
+    if (data) {
+        _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
+    }
+}
+
+
+
+static jlong
+nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
+{
+    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con, type, kind, norm, size);
+    return (jlong)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind, norm, size);
+}
+
+static jlong
+nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
+                jintArray _ids, jobjectArray _names, jintArray _arraySizes)
+{
+    int fieldCount = _env->GetArrayLength(_ids);
+    LOG_API("nElementCreate2, con(%p)", (RsContext)con);
+
+    jint *ids = _env->GetIntArrayElements(_ids, NULL);
+    jint *arraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
+
+    AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
+
+    const char **nameArray = names.c_str();
+    size_t *sizeArray = names.c_str_len();
+
+    jlong id = (jlong)rsElementCreate2((RsContext)con,
+                                     (RsElement *)ids, fieldCount,
+                                     nameArray, fieldCount * sizeof(size_t),  sizeArray,
+                                     (const uint32_t *)arraySizes, fieldCount);
+
+    _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
+    _env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
+    return (jlong)id;
+}
+
+static void
+nElementGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jintArray _elementData)
+{
+    int dataSize = _env->GetArrayLength(_elementData);
+    LOG_API("nElementGetNativeData, con(%p)", (RsContext)con);
+
+    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
+    assert(dataSize == 5);
+
+    uint32_t elementData[5];
+    rsaElementGetNativeData((RsContext)con, (RsElement)id, elementData, dataSize);
+
+    for(jint i = 0; i < dataSize; i ++) {
+        _env->SetIntArrayRegion(_elementData, i, 1, (const jint*)&elementData[i]);
+    }
+}
+
+
+static void
+nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
+                       jintArray _IDs,
+                       jobjectArray _names,
+                       jintArray _arraySizes)
+{
+    int dataSize = _env->GetArrayLength(_IDs);
+    LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
+
+    uint32_t *ids = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
+    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
+    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
+
+    rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes, (uint32_t)dataSize);
+
+    for(jint i = 0; i < dataSize; i++) {
+        _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
+        _env->SetIntArrayRegion(_IDs, i, 1, (const jint*)&ids[i]);
+        _env->SetIntArrayRegion(_arraySizes, i, 1, (const jint*)&arraySizes[i]);
+    }
+
+    free(ids);
+    free(names);
+    free(arraySizes);
+}
+
+// -----------------------------------
+
+static jlong
+nTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid,
+            jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv)
+{
+    LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
+            (RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
+
+    return (jlong)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
+}
+
+static void
+nTypeGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jintArray _typeData)
+{
+    // We are packing 6 items: mDimX; mDimY; mDimZ;
+    // mDimLOD; mDimFaces; mElement; into typeData
+    int elementCount = _env->GetArrayLength(_typeData);
+
+    assert(elementCount == 6);
+    LOG_API("nTypeGetNativeData, con(%p)", (RsContext)con);
+
+    uint32_t typeData[6];
+    rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
+
+    for(jint i = 0; i < elementCount; i ++) {
+        _env->SetIntArrayRegion(_typeData, i, 1, (const jint*)&typeData[i]);
+    }
+}
+
+// -----------------------------------
+
+static jlong
+nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jint pointer)
+{
+    LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
+    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
+}
+
+static void
+nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits)
+{
+    LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", (RsContext)con, (RsAllocation)a, bits);
+    rsAllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
+}
+
+static jobject
+nAllocationGetSurface(JNIEnv *_env, jobject _this, jlong con, jlong a)
+{
+    LOG_API("nAllocationGetSurface, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
+
+    IGraphicBufferProducer *v = (IGraphicBufferProducer *)rsAllocationGetSurface((RsContext)con, (RsAllocation)a);
+    sp<IGraphicBufferProducer> bp = v;
+    v->decStrong(NULL);
+
+    jobject o = android_view_Surface_createFromIGraphicBufferProducer(_env, bp);
+    return o;
+}
+
+static void
+nAllocationSetSurface(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject sur)
+{
+    LOG_API("nAllocationSetSurface, con(%p), alloc(%p), surface(%p)",
+            (RsContext)con, (RsAllocation)alloc, (Surface *)sur);
+
+    sp<Surface> s;
+    if (sur != 0) {
+        s = android_view_Surface_getSurface(_env, sur);
+    }
+
+    rsAllocationSetSurface((RsContext)con, (RsAllocation)alloc, static_cast<ANativeWindow *>(s.get()));
+}
+
+static void
+nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
+{
+    LOG_API("nAllocationIoSend, con(%p), alloc(%p)", (RsContext)con, alloc);
+    rsAllocationIoSend((RsContext)con, (RsAllocation)alloc);
+}
+
+static void
+nAllocationIoReceive(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
+{
+    LOG_API("nAllocationIoReceive, con(%p), alloc(%p)", (RsContext)con, alloc);
+    rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
+}
+
+
+static void
+nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
+{
+    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", (RsContext)con, (RsAllocation)alloc);
+    rsAllocationGenerateMipmaps((RsContext)con, (RsAllocation)alloc);
+}
+
+static jlong
+nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, jobject jbitmap, jint usage)
+{
+    SkBitmap const * nativeBitmap =
+            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+    const SkBitmap& bitmap(*nativeBitmap);
+
+    bitmap.lockPixels();
+    const void* ptr = bitmap.getPixels();
+    jlong id = (jlong)rsAllocationCreateFromBitmap((RsContext)con,
+                                                  (RsType)type, (RsAllocationMipmapControl)mip,
+                                                  ptr, bitmap.getSize(), usage);
+    bitmap.unlockPixels();
+    return id;
+}
+
+static jlong
+nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, jobject jbitmap, jint usage)
+{
+    SkBitmap const * nativeBitmap =
+            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+    const SkBitmap& bitmap(*nativeBitmap);
+
+    bitmap.lockPixels();
+    const void* ptr = bitmap.getPixels();
+    jlong id = (jlong)rsAllocationCreateTyped((RsContext)con,
+                                            (RsType)type, (RsAllocationMipmapControl)mip,
+                                            (uint32_t)usage, (size_t)ptr);
+    bitmap.unlockPixels();
+    return id;
+}
+
+static jlong
+nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, jobject jbitmap, jint usage)
+{
+    SkBitmap const * nativeBitmap =
+            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+    const SkBitmap& bitmap(*nativeBitmap);
+
+    bitmap.lockPixels();
+    const void* ptr = bitmap.getPixels();
+    jlong id = (jlong)rsAllocationCubeCreateFromBitmap((RsContext)con,
+                                                      (RsType)type, (RsAllocationMipmapControl)mip,
+                                                      ptr, bitmap.getSize(), usage);
+    bitmap.unlockPixels();
+    return id;
+}
+
+static void
+nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
+{
+    SkBitmap const * nativeBitmap =
+            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+    const SkBitmap& bitmap(*nativeBitmap);
+    int w = bitmap.width();
+    int h = bitmap.height();
+
+    bitmap.lockPixels();
+    const void* ptr = bitmap.getPixels();
+    rsAllocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0,
+                       0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
+                       w, h, ptr, bitmap.getSize(), 0);
+    bitmap.unlockPixels();
+}
+
+static void
+nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
+{
+    SkBitmap const * nativeBitmap =
+            (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+    const SkBitmap& bitmap(*nativeBitmap);
+
+    bitmap.lockPixels();
+    void* ptr = bitmap.getPixels();
+    rsAllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, ptr, bitmap.getSize());
+    bitmap.unlockPixels();
+    bitmap.notifyPixelsChanged();
+}
+
+static void ReleaseBitmapCallback(void *bmp)
+{
+    SkBitmap const * nativeBitmap = (SkBitmap const *)bmp;
+    nativeBitmap->unlockPixels();
+}
+
+
+static void
+nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
+                  jint count, jobject data, jint sizeBytes, jint dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), dataType(%i)",
+            (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes, dataType);
+    PER_ARRAY_TYPE(NULL, rsAllocation1DData, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
+}
+
+static void
+//    native void rsnAllocationElementData1D(long con, long id, int xoff, int compIdx, byte[] d, int sizeBytes);
+nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
+{
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsAllocation1DElementData((RsContext)con, (RsAllocation)alloc, offset, lod, ptr, sizeBytes, compIdx);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
+                  jint w, jint h, jobject data, jint sizeBytes, jint dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
+    LOG_API("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) type(%i)",
+            (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
+    PER_ARRAY_TYPE(NULL, rsAllocation2DData, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
+}
+
+static void
+nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con,
+                        jlong dstAlloc, jint dstXoff, jint dstYoff,
+                        jint dstMip, jint dstFace,
+                        jint width, jint height,
+                        jlong srcAlloc, jint srcXoff, jint srcYoff,
+                        jint srcMip, jint srcFace)
+{
+    LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
+            " dstMip(%i), dstFace(%i), width(%i), height(%i),"
+            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
+            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
+            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
+
+    rsAllocationCopy2DRange((RsContext)con,
+                            (RsAllocation)dstAlloc,
+                            dstXoff, dstYoff,
+                            dstMip, dstFace,
+                            width, height,
+                            (RsAllocation)srcAlloc,
+                            srcXoff, srcYoff,
+                            srcMip, srcFace);
+}
+
+static void
+nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
+                    jint w, jint h, jint d, jobject data, int sizeBytes, int dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    LOG_API("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i), h(%i), d(%i), sizeBytes(%i)",
+            (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, lod, w, h, d, sizeBytes);
+    PER_ARRAY_TYPE(NULL, rsAllocation3DData, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
+}
+
+static void
+nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con,
+                        jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
+                        jint dstMip,
+                        jint width, jint height, jint depth,
+                        jlong srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff,
+                        jint srcMip)
+{
+    LOG_API("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i),"
+            " dstMip(%i), width(%i), height(%i),"
+            " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)",
+            (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip,
+            width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip);
+
+    rsAllocationCopy3DRange((RsContext)con,
+                            (RsAllocation)dstAlloc,
+                            dstXoff, dstYoff, dstZoff, dstMip,
+                            width, height, depth,
+                            (RsAllocation)srcAlloc,
+                            srcXoff, srcYoff, srcZoff, srcMip);
+}
+
+
+static void
+nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, int dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
+    PER_ARRAY_TYPE(0, rsAllocationRead, (RsContext)con, alloc, ptr, len * typeBytes);
+}
+
+static void
+nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
+                  jint count, jobject data, int sizeBytes, int dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    LOG_API("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), dataType(%i)",
+            (RsContext)con, alloc, offset, count, sizeBytes, dataType);
+    PER_ARRAY_TYPE(0, rsAllocation1DRead, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
+}
+
+static void
+nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
+                  jint w, jint h, jobject data, int sizeBytes, int dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
+    LOG_API("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) type(%i)",
+            (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
+    PER_ARRAY_TYPE(0, rsAllocation2DRead, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
+}
+
+static jlong
+nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
+{
+    LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
+    return (jlong) rsaAllocationGetType((RsContext)con, (RsAllocation)a);
+}
+
+static void
+nAllocationResize1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint dimX)
+{
+    LOG_API("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", (RsContext)con, (RsAllocation)alloc, dimX);
+    rsAllocationResize1D((RsContext)con, (RsAllocation)alloc, dimX);
+}
+
+// -----------------------------------
+
+static jlong
+nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con, jlong native_asset)
+{
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    ALOGV("______nFileA3D %p", asset);
+
+    jlong id = (jlong)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
+    return id;
+}
+
+static jlong
+nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path)
+{
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    if (mgr == NULL) {
+        return 0;
+    }
+
+    AutoJavaStringToUTF8 str(_env, _path);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == NULL) {
+        return 0;
+    }
+
+    jlong id = (jlong)rsaFileA3DCreateFromAsset((RsContext)con, asset);
+    return id;
+}
+
+static jlong
+nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, jlong con, jstring fileName)
+{
+    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
+    jlong id = (jlong)rsaFileA3DCreateFromFile((RsContext)con, fileNameUTF.c_str());
+
+    return id;
+}
+
+static jint
+nFileA3DGetNumIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D)
+{
+    int32_t numEntries = 0;
+    rsaFileA3DGetNumIndexEntries((RsContext)con, &numEntries, (RsFile)fileA3D);
+    return (jint)numEntries;
+}
+
+static void
+nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries)
+{
+    ALOGV("______nFileA3D %p", (RsFile) fileA3D);
+    RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
+
+    rsaFileA3DGetIndexEntries((RsContext)con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
+
+    for(jint i = 0; i < numEntries; i ++) {
+        _env->SetObjectArrayElement(_entries, i, _env->NewStringUTF(fileEntries[i].objectName));
+        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&fileEntries[i].classID);
+    }
+
+    free(fileEntries);
+}
+
+static jlong
+nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index)
+{
+    ALOGV("______nFileA3D %p", (RsFile) fileA3D);
+    jlong id = (jlong)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
+    return id;
+}
+
+// -----------------------------------
+
+static jlong
+nFontCreateFromFile(JNIEnv *_env, jobject _this, jlong con,
+                    jstring fileName, jfloat fontSize, jint dpi)
+{
+    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
+    jlong id = (jlong)rsFontCreateFromFile((RsContext)con,
+                                         fileNameUTF.c_str(), fileNameUTF.length(),
+                                         fontSize, dpi);
+
+    return id;
+}
+
+static jlong
+nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con,
+                           jstring name, jfloat fontSize, jint dpi, jlong native_asset)
+{
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    AutoJavaStringToUTF8 nameUTF(_env, name);
+
+    jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
+                                           nameUTF.c_str(), nameUTF.length(),
+                                           fontSize, dpi,
+                                           asset->getBuffer(false), asset->getLength());
+    return id;
+}
+
+static jlong
+nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
+                     jfloat fontSize, jint dpi)
+{
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    if (mgr == NULL) {
+        return 0;
+    }
+
+    AutoJavaStringToUTF8 str(_env, _path);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == NULL) {
+        return 0;
+    }
+
+    jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
+                                           str.c_str(), str.length(),
+                                           fontSize, dpi,
+                                           asset->getBuffer(false), asset->getLength());
+    delete asset;
+    return id;
+}
+
+// -----------------------------------
+
+static void
+nScriptBindAllocation(JNIEnv *_env, jobject _this, jlong con, jlong script, jlong alloc, jint slot)
+{
+    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", (RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
+    rsScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot);
+}
+
+static void
+nScriptSetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jint val)
+{
+    LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con, (void *)script, slot, val);
+    rsScriptSetVarI((RsContext)con, (RsScript)script, slot, val);
+}
+
+static jint
+nScriptGetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot)
+{
+    LOG_API("nScriptGetVarI, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    int value = 0;
+    rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value));
+    return value;
+}
+
+static void
+nScriptSetVarObj(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val)
+{
+    LOG_API("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con, (void *)script, slot, val);
+    rsScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val);
+}
+
+static void
+nScriptSetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val)
+{
+    LOG_API("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%lli)", (RsContext)con, (void *)script, slot, val);
+    rsScriptSetVarJ((RsContext)con, (RsScript)script, slot, val);
+}
+
+static jlong
+nScriptGetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot)
+{
+    LOG_API("nScriptGetVarJ, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jlong value = 0;
+    rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value));
+    return value;
+}
+
+static void
+nScriptSetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, float val)
+{
+    LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", (RsContext)con, (void *)script, slot, val);
+    rsScriptSetVarF((RsContext)con, (RsScript)script, slot, val);
+}
+
+static jfloat
+nScriptGetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot)
+{
+    LOG_API("nScriptGetVarF, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jfloat value = 0;
+    rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value));
+    return value;
+}
+
+static void
+nScriptSetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, double val)
+{
+    LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", (RsContext)con, (void *)script, slot, val);
+    rsScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
+}
+
+static jdouble
+nScriptGetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot)
+{
+    LOG_API("nScriptGetVarD, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jdouble value = 0;
+    rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value));
+    return value;
+}
+
+static void
+nScriptSetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data)
+{
+    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jint len = _env->GetArrayLength(data);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nScriptGetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data)
+{
+    LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jint len = _env->GetArrayLength(data);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsScriptGetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nScriptSetVarVE(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, jlong elem, jintArray dims)
+{
+    LOG_API("nScriptSetVarVE, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jint len = _env->GetArrayLength(data);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
+    jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
+    rsScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
+                     (const size_t*) dimsPtr, dimsLen);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+    _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
+}
+
+
+static void
+nScriptSetTimeZone(JNIEnv *_env, jobject _this, jlong con, jlong script, jbyteArray timeZone)
+{
+    LOG_API("nScriptCSetTimeZone, con(%p), s(%p)", (RsContext)con, (void *)script);
+
+    jint length = _env->GetArrayLength(timeZone);
+    jbyte* timeZone_ptr;
+    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
+
+    rsScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length);
+
+    if (timeZone_ptr) {
+        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
+    }
+}
+
+static void
+nScriptInvoke(JNIEnv *_env, jobject _this, jlong con, jlong obj, jint slot)
+{
+    LOG_API("nScriptInvoke, con(%p), script(%p)", (RsContext)con, (void *)obj);
+    rsScriptInvoke((RsContext)con, (RsScript)obj, slot);
+}
+
+static void
+nScriptInvokeV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data)
+{
+    LOG_API("nScriptInvokeV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jint len = _env->GetArrayLength(data);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nScriptForEach(JNIEnv *_env, jobject _this, jlong con,
+               jlong script, jint slot, jlong ain, jlong aout)
+{
+    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    rsScriptForEach((RsContext)con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, NULL, 0, NULL, 0);
+}
+static void
+nScriptForEachV(JNIEnv *_env, jobject _this, jlong con,
+                jlong script, jint slot, jlong ain, jlong aout, jbyteArray params)
+{
+    LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jint len = _env->GetArrayLength(params);
+    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
+    rsScriptForEach((RsContext)con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, ptr, len, NULL, 0);
+    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
+}
+
+static void
+nScriptForEachClipped(JNIEnv *_env, jobject _this, jlong con,
+                      jlong script, jint slot, jlong ain, jlong aout,
+                      jint xstart, jint xend,
+                      jint ystart, jint yend, jint zstart, jint zend)
+{
+    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    RsScriptCall sc;
+    sc.xStart = xstart;
+    sc.xEnd = xend;
+    sc.yStart = ystart;
+    sc.yEnd = yend;
+    sc.zStart = zstart;
+    sc.zEnd = zend;
+    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    sc.arrayStart = 0;
+    sc.arrayEnd = 0;
+    rsScriptForEach((RsContext)con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, NULL, 0, &sc, sizeof(sc));
+}
+
+static void
+nScriptForEachClippedV(JNIEnv *_env, jobject _this, jlong con,
+                       jlong script, jint slot, jlong ain, jlong aout,
+                       jbyteArray params, jint xstart, jint xend,
+                       jint ystart, jint yend, jint zstart, jint zend)
+{
+    LOG_API("nScriptForEachClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+    jint len = _env->GetArrayLength(params);
+    jbyte *ptr = _env->GetByteArrayElements(params, NULL);
+    RsScriptCall sc;
+    sc.xStart = xstart;
+    sc.xEnd = xend;
+    sc.yStart = ystart;
+    sc.yEnd = yend;
+    sc.zStart = zstart;
+    sc.zEnd = zend;
+    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    sc.arrayStart = 0;
+    sc.arrayEnd = 0;
+    rsScriptForEach((RsContext)con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, ptr, len, &sc, sizeof(sc));
+    _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
+}
+
+// -----------------------------------
+
+static jlong
+nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
+               jstring resName, jstring cacheDir,
+               jbyteArray scriptRef, jint length)
+{
+    LOG_API("nScriptCCreate, con(%p)", (RsContext)con);
+
+    AutoJavaStringToUTF8 resNameUTF(_env, resName);
+    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
+    jlong ret = 0;
+    jbyte* script_ptr = NULL;
+    jint _exception = 0;
+    jint remaining;
+    if (!scriptRef) {
+        _exception = 1;
+        //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null");
+        goto exit;
+    }
+    if (length < 0) {
+        _exception = 1;
+        //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0");
+        goto exit;
+    }
+    remaining = _env->GetArrayLength(scriptRef);
+    if (remaining < length) {
+        _exception = 1;
+        //jniThrowException(_env, "java/lang/IllegalArgumentException",
+        //        "length > script.length - offset");
+        goto exit;
+    }
+    script_ptr = (jbyte *)
+        _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
+
+    //rsScriptCSetText((RsContext)con, (const char *)script_ptr, length);
+
+    ret = (jlong)rsScriptCCreate((RsContext)con,
+                                resNameUTF.c_str(), resNameUTF.length(),
+                                cacheDirUTF.c_str(), cacheDirUTF.length(),
+                                (const char *)script_ptr, length);
+
+exit:
+    if (script_ptr) {
+        _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr,
+                _exception ? JNI_ABORT: 0);
+    }
+
+    return (jlong)ret;
+}
+
+static jlong
+nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid)
+{
+    LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
+    return (jlong)rsScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
+}
+
+static jlong
+nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig)
+{
+    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con, (void *)sid, slot, sig);
+    return (jlong)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
+}
+
+static jlong
+nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
+{
+    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
+    return (jlong)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
+}
+
+static jlong
+nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jintArray _kernels, jintArray _src,
+    jintArray _dstk, jintArray _dstf, jintArray _types)
+{
+    LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
+
+    jint kernelsLen = _env->GetArrayLength(_kernels) * sizeof(int);
+    jint *kernelsPtr = _env->GetIntArrayElements(_kernels, NULL);
+    jint srcLen = _env->GetArrayLength(_src) * sizeof(int);
+    jint *srcPtr = _env->GetIntArrayElements(_src, NULL);
+    jint dstkLen = _env->GetArrayLength(_dstk) * sizeof(int);
+    jint *dstkPtr = _env->GetIntArrayElements(_dstk, NULL);
+    jint dstfLen = _env->GetArrayLength(_dstf) * sizeof(int);
+    jint *dstfPtr = _env->GetIntArrayElements(_dstf, NULL);
+    jint typesLen = _env->GetArrayLength(_types) * sizeof(int);
+    jint *typesPtr = _env->GetIntArrayElements(_types, NULL);
+
+    int id = (int)rsScriptGroupCreate((RsContext)con,
+                               (RsScriptKernelID *)kernelsPtr, kernelsLen,
+                               (RsScriptKernelID *)srcPtr, srcLen,
+                               (RsScriptKernelID *)dstkPtr, dstkLen,
+                               (RsScriptFieldID *)dstfPtr, dstfLen,
+                               (RsType *)typesPtr, typesLen);
+
+    _env->ReleaseIntArrayElements(_kernels, kernelsPtr, 0);
+    _env->ReleaseIntArrayElements(_src, srcPtr, 0);
+    _env->ReleaseIntArrayElements(_dstk, dstkPtr, 0);
+    _env->ReleaseIntArrayElements(_dstf, dstfPtr, 0);
+    _env->ReleaseIntArrayElements(_types, typesPtr, 0);
+    return id;
+}
+
+static void
+nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
+{
+    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
+        (void *)gid, (void *)kid, (void *)alloc);
+    rsScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
+}
+
+static void
+nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc)
+{
+    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con,
+        (void *)gid, (void *)kid, (void *)alloc);
+    rsScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
+}
+
+static void
+nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid)
+{
+    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid);
+    rsScriptGroupExecute((RsContext)con, (RsScriptGroup)gid);
+}
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nProgramStoreCreate(JNIEnv *_env, jobject _this, jlong con,
+                    jboolean colorMaskR, jboolean colorMaskG, jboolean colorMaskB, jboolean colorMaskA,
+                    jboolean depthMask, jboolean ditherEnable,
+                    jint srcFunc, jint destFunc,
+                    jint depthFunc)
+{
+    LOG_API("nProgramStoreCreate, con(%p)", (RsContext)con);
+    return (jlong)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+                                      depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
+                                      (RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
+}
+
+// ---------------------------------------------------------------------------
+
+static void
+nProgramBindConstants(JNIEnv *_env, jobject _this, jlong con, jlong vpv, jint slot, jlong a)
+{
+    LOG_API("nProgramBindConstants, con(%p), vpf(%p), sloat(%i), a(%p)", (RsContext)con, (RsProgramVertex)vpv, slot, (RsAllocation)a);
+    rsProgramBindConstants((RsContext)con, (RsProgram)vpv, slot, (RsAllocation)a);
+}
+
+static void
+nProgramBindTexture(JNIEnv *_env, jobject _this, jlong con, jlong vpf, jint slot, jlong a)
+{
+    LOG_API("nProgramBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", (RsContext)con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
+    rsProgramBindTexture((RsContext)con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
+}
+
+static void
+nProgramBindSampler(JNIEnv *_env, jobject _this, jlong con, jlong vpf, jint slot, jlong a)
+{
+    LOG_API("nProgramBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", (RsContext)con, (RsProgramFragment)vpf, slot, (RsSampler)a);
+    rsProgramBindSampler((RsContext)con, (RsProgramFragment)vpf, slot, (RsSampler)a);
+}
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nProgramFragmentCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader,
+                       jobjectArray texNames, jintArray params)
+{
+    AutoJavaStringToUTF8 shaderUTF(_env, shader);
+    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jint paramLen = _env->GetArrayLength(params);
+
+    int texCount = _env->GetArrayLength(texNames);
+    AutoJavaStringArrayToUTF8 names(_env, texNames, texCount);
+    const char ** nameArray = names.c_str();
+    size_t* sizeArray = names.c_str_len();
+
+    LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen);
+
+    jlong ret = (jlong)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
+                                             nameArray, texCount, sizeArray,
+                                             (uint32_t *)paramPtr, paramLen);
+
+    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    return ret;
+}
+
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nProgramVertexCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader,
+                     jobjectArray texNames, jintArray params)
+{
+    AutoJavaStringToUTF8 shaderUTF(_env, shader);
+    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jint paramLen = _env->GetArrayLength(params);
+
+    LOG_API("nProgramVertexCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen);
+
+    int texCount = _env->GetArrayLength(texNames);
+    AutoJavaStringArrayToUTF8 names(_env, texNames, texCount);
+    const char ** nameArray = names.c_str();
+    size_t* sizeArray = names.c_str_len();
+
+    jlong ret = (jlong)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
+                                           nameArray, texCount, sizeArray,
+                                           (uint32_t *)paramPtr, paramLen);
+
+    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    return ret;
+}
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nProgramRasterCreate(JNIEnv *_env, jobject _this, jlong con, jboolean pointSprite, jint cull)
+{
+    LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", (RsContext)con, pointSprite, cull);
+    return (jlong)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
+}
+
+
+// ---------------------------------------------------------------------------
+
+static void
+nContextBindRootScript(JNIEnv *_env, jobject _this, jlong con, jint script)
+{
+    LOG_API("nContextBindRootScript, con(%p), script(%p)", (RsContext)con, (RsScript)script);
+    rsContextBindRootScript((RsContext)con, (RsScript)script);
+}
+
+static void
+nContextBindProgramStore(JNIEnv *_env, jobject _this, jlong con, jint pfs)
+{
+    LOG_API("nContextBindProgramStore, con(%p), pfs(%p)", (RsContext)con, (RsProgramStore)pfs);
+    rsContextBindProgramStore((RsContext)con, (RsProgramStore)pfs);
+}
+
+static void
+nContextBindProgramFragment(JNIEnv *_env, jobject _this, jlong con, jint pf)
+{
+    LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", (RsContext)con, (RsProgramFragment)pf);
+    rsContextBindProgramFragment((RsContext)con, (RsProgramFragment)pf);
+}
+
+static void
+nContextBindProgramVertex(JNIEnv *_env, jobject _this, jlong con, jint pf)
+{
+    LOG_API("nContextBindProgramVertex, con(%p), pf(%p)", (RsContext)con, (RsProgramVertex)pf);
+    rsContextBindProgramVertex((RsContext)con, (RsProgramVertex)pf);
+}
+
+static void
+nContextBindProgramRaster(JNIEnv *_env, jobject _this, jlong con, jint pf)
+{
+    LOG_API("nContextBindProgramRaster, con(%p), pf(%p)", (RsContext)con, (RsProgramRaster)pf);
+    rsContextBindProgramRaster((RsContext)con, (RsProgramRaster)pf);
+}
+
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
+               jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
+{
+    LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
+    return (jlong)rsSamplerCreate((RsContext)con,
+                                 (RsSamplerValue)magFilter,
+                                 (RsSamplerValue)minFilter,
+                                 (RsSamplerValue)wrapS,
+                                 (RsSamplerValue)wrapT,
+                                 (RsSamplerValue)wrapR,
+                                 aniso);
+}
+
+// ---------------------------------------------------------------------------
+
+static jlong
+nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jlong _loop, jfloat q) {
+    LOG_API("nPathCreate, con(%p)", (RsContext)con);
+
+    jlong id = (jlong)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
+                                   (RsAllocation)_vtx,
+                                   (RsAllocation)_loop, q);
+    return id;
+}
+
+static jlong
+nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jintArray _vtx, jintArray _idx, jintArray _prim)
+{
+    LOG_API("nMeshCreate, con(%p)", (RsContext)con);
+
+    jint vtxLen = _env->GetArrayLength(_vtx);
+    jint *vtxPtr = _env->GetIntArrayElements(_vtx, NULL);
+    jint idxLen = _env->GetArrayLength(_idx);
+    jint *idxPtr = _env->GetIntArrayElements(_idx, NULL);
+    jint primLen = _env->GetArrayLength(_prim);
+    jint *primPtr = _env->GetIntArrayElements(_prim, NULL);
+
+    int id = (int)rsMeshCreate((RsContext)con,
+                               (RsAllocation *)vtxPtr, vtxLen,
+                               (RsAllocation *)idxPtr, idxLen,
+                               (uint32_t *)primPtr, primLen);
+
+    _env->ReleaseIntArrayElements(_vtx, vtxPtr, 0);
+    _env->ReleaseIntArrayElements(_idx, idxPtr, 0);
+    _env->ReleaseIntArrayElements(_prim, primPtr, 0);
+    return id;
+}
+
+static jint
+nMeshGetVertexBufferCount(JNIEnv *_env, jobject _this, jlong con, jlong mesh)
+{
+    LOG_API("nMeshGetVertexBufferCount, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
+    jint vtxCount = 0;
+    rsaMeshGetVertexBufferCount((RsContext)con, (RsMesh)mesh, &vtxCount);
+    return vtxCount;
+}
+
+static jint
+nMeshGetIndexCount(JNIEnv *_env, jobject _this, jlong con, jlong mesh)
+{
+    LOG_API("nMeshGetIndexCount, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
+    jint idxCount = 0;
+    rsaMeshGetIndexCount((RsContext)con, (RsMesh)mesh, &idxCount);
+    return idxCount;
+}
+
+static void
+nMeshGetVertices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jintArray _ids, int numVtxIDs)
+{
+    LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
+
+    RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numVtxIDs * sizeof(RsAllocation));
+    rsaMeshGetVertices((RsContext)con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
+
+    for(jint i = 0; i < numVtxIDs; i ++) {
+        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&allocs[i]);
+    }
+
+    free(allocs);
+}
+
+static void
+nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jintArray _idxIds, jintArray _primitives, int numIndices)
+{
+    LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
+
+    RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numIndices * sizeof(RsAllocation));
+    uint32_t *prims= (uint32_t*)malloc((uint32_t)numIndices * sizeof(uint32_t));
+
+    rsaMeshGetIndices((RsContext)con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
+
+    for(jint i = 0; i < numIndices; i ++) {
+        _env->SetIntArrayRegion(_idxIds, i, 1, (const jint*)&allocs[i]);
+        _env->SetIntArrayRegion(_primitives, i, 1, (const jint*)&prims[i]);
+    }
+
+    free(allocs);
+    free(prims);
+}
+
+// ---------------------------------------------------------------------------
+
+
+static const char *classPathName = "android/renderscript/RenderScript";
+
+static JNINativeMethod methods[] = {
+{"_nInit",                         "()V",                                     (void*)_nInit },
+
+{"nDeviceCreate",                  "()J",                                     (void*)nDeviceCreate },
+{"nDeviceDestroy",                 "(J)V",                                    (void*)nDeviceDestroy },
+{"nDeviceSetConfig",               "(JII)V",                                  (void*)nDeviceSetConfig },
+{"nContextGetUserMessage",         "(J[I)I",                                  (void*)nContextGetUserMessage },
+{"nContextGetErrorMessage",        "(J)Ljava/lang/String;",                   (void*)nContextGetErrorMessage },
+{"nContextPeekMessage",            "(J[I)I",                                  (void*)nContextPeekMessage },
+
+{"nContextInitToClient",           "(J)V",                                    (void*)nContextInitToClient },
+{"nContextDeinitToClient",         "(J)V",                                    (void*)nContextDeinitToClient },
+
+
+// All methods below are thread protected in java.
+{"rsnContextCreate",                 "(JIII)J",                               (void*)nContextCreate },
+{"rsnContextCreateGL",               "(JIIIIIIIIIIIIFI)J",                    (void*)nContextCreateGL },
+{"rsnContextFinish",                 "(J)V",                                  (void*)nContextFinish },
+{"rsnContextSetPriority",            "(JI)V",                                 (void*)nContextSetPriority },
+{"rsnContextSetSurface",             "(JIILandroid/view/Surface;)V",          (void*)nContextSetSurface },
+{"rsnContextDestroy",                "(J)V",                                  (void*)nContextDestroy },
+{"rsnContextDump",                   "(JI)V",                                 (void*)nContextDump },
+{"rsnContextPause",                  "(J)V",                                  (void*)nContextPause },
+{"rsnContextResume",                 "(J)V",                                  (void*)nContextResume },
+{"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
+{"rsnAssignName",                    "(JJ[B)V",                               (void*)nAssignName },
+{"rsnGetName",                       "(JJ)Ljava/lang/String;",                (void*)nGetName },
+{"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
+
+{"rsnFileA3DCreateFromFile",         "(JLjava/lang/String;)J",                (void*)nFileA3DCreateFromFile },
+{"rsnFileA3DCreateFromAssetStream",  "(JJ)J",                                 (void*)nFileA3DCreateFromAssetStream },
+{"rsnFileA3DCreateFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;)J",            (void*)nFileA3DCreateFromAsset },
+{"rsnFileA3DGetNumIndexEntries",     "(JJ)I",                                 (void*)nFileA3DGetNumIndexEntries },
+{"rsnFileA3DGetIndexEntries",        "(JJI[I[Ljava/lang/String;)V",           (void*)nFileA3DGetIndexEntries },
+{"rsnFileA3DGetEntryByIndex",        "(JJI)J",                                (void*)nFileA3DGetEntryByIndex },
+
+{"rsnFontCreateFromFile",            "(JLjava/lang/String;FI)J",              (void*)nFontCreateFromFile },
+{"rsnFontCreateFromAssetStream",     "(JLjava/lang/String;FIJ)J",             (void*)nFontCreateFromAssetStream },
+{"rsnFontCreateFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)J",            (void*)nFontCreateFromAsset },
+
+{"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
+{"rsnElementCreate2",                "(J[I[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
+{"rsnElementGetNativeData",          "(JJ[I)V",                               (void*)nElementGetNativeData },
+{"rsnElementGetSubElements",         "(JJ[I[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
+
+{"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
+{"rsnTypeGetNativeData",             "(JJ[I)V",                               (void*)nTypeGetNativeData },
+
+{"rsnAllocationCreateTyped",         "(JJIII)J",                               (void*)nAllocationCreateTyped },
+{"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
+{"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
+{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
+
+{"rsnAllocationCopyFromBitmap",      "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
+{"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
+
+{"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
+{"rsnAllocationGetSurface",          "(JJ)Landroid/view/Surface;",            (void*)nAllocationGetSurface },
+{"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
+{"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
+{"rsnAllocationIoReceive",           "(JJ)V",                                 (void*)nAllocationIoReceive },
+{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationData1D },
+{"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
+{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationData2D },
+{"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
+{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;II)V",      (void*)nAllocationData3D },
+{"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
+{"rsnAllocationRead",                "(JJLjava/lang/Object;I)V",              (void*)nAllocationRead },
+{"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationRead1D },
+{"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationRead2D },
+{"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
+{"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
+{"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
+
+{"rsnScriptBindAllocation",          "(JJJI)V",                               (void*)nScriptBindAllocation },
+{"rsnScriptSetTimeZone",             "(JJ[B)V",                               (void*)nScriptSetTimeZone },
+{"rsnScriptInvoke",                  "(JJI)V",                                (void*)nScriptInvoke },
+{"rsnScriptInvokeV",                 "(JJI[B)V",                              (void*)nScriptInvokeV },
+{"rsnScriptForEach",                 "(JJIJJ)V",                              (void*)nScriptForEach },
+{"rsnScriptForEach",                 "(JJIJJ[B)V",                            (void*)nScriptForEachV },
+{"rsnScriptForEachClipped",          "(JJIJJIIIIII)V",                        (void*)nScriptForEachClipped },
+{"rsnScriptForEachClipped",          "(JJIJJ[BIIIIII)V",                      (void*)nScriptForEachClippedV },
+{"rsnScriptSetVarI",                 "(JJII)V",                               (void*)nScriptSetVarI },
+{"rsnScriptGetVarI",                 "(JJI)I",                                (void*)nScriptGetVarI },
+{"rsnScriptSetVarJ",                 "(JJIJ)V",                               (void*)nScriptSetVarJ },
+{"rsnScriptGetVarJ",                 "(JJI)J",                                (void*)nScriptGetVarJ },
+{"rsnScriptSetVarF",                 "(JJIF)V",                               (void*)nScriptSetVarF },
+{"rsnScriptGetVarF",                 "(JJI)F",                                (void*)nScriptGetVarF },
+{"rsnScriptSetVarD",                 "(JJID)V",                               (void*)nScriptSetVarD },
+{"rsnScriptGetVarD",                 "(JJI)D",                                (void*)nScriptGetVarD },
+{"rsnScriptSetVarV",                 "(JJI[B)V",                              (void*)nScriptSetVarV },
+{"rsnScriptGetVarV",                 "(JJI[B)V",                              (void*)nScriptGetVarV },
+{"rsnScriptSetVarVE",                "(JJI[BJ[I)V",                           (void*)nScriptSetVarVE },
+{"rsnScriptSetVarObj",               "(JJIJ)V",                               (void*)nScriptSetVarObj },
+
+{"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
+{"rsnScriptIntrinsicCreate",         "(JIJ)J",                                (void*)nScriptIntrinsicCreate },
+{"rsnScriptKernelIDCreate",          "(JJII)J",                               (void*)nScriptKernelIDCreate },
+{"rsnScriptFieldIDCreate",           "(JJI)J",                                (void*)nScriptFieldIDCreate },
+{"rsnScriptGroupCreate",             "(J[I[I[I[I[I)J",                        (void*)nScriptGroupCreate },
+{"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
+{"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
+{"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
+
+{"rsnProgramStoreCreate",            "(JZZZZZZIII)J",                         (void*)nProgramStoreCreate },
+
+{"rsnProgramBindConstants",          "(JJIJ)V",                               (void*)nProgramBindConstants },
+{"rsnProgramBindTexture",            "(JJIJ)V",                               (void*)nProgramBindTexture },
+{"rsnProgramBindSampler",            "(JJIJ)V",                               (void*)nProgramBindSampler },
+
+{"rsnProgramFragmentCreate",         "(JLjava/lang/String;[Ljava/lang/String;[I)J",              (void*)nProgramFragmentCreate },
+{"rsnProgramRasterCreate",           "(JZI)J",                                (void*)nProgramRasterCreate },
+{"rsnProgramVertexCreate",           "(JLjava/lang/String;[Ljava/lang/String;[I)J",              (void*)nProgramVertexCreate },
+
+{"rsnContextBindRootScript",         "(JI)V",                                 (void*)nContextBindRootScript },
+{"rsnContextBindProgramStore",       "(JI)V",                                 (void*)nContextBindProgramStore },
+{"rsnContextBindProgramFragment",    "(JI)V",                                 (void*)nContextBindProgramFragment },
+{"rsnContextBindProgramVertex",      "(JI)V",                                 (void*)nContextBindProgramVertex },
+{"rsnContextBindProgramRaster",      "(JI)V",                                 (void*)nContextBindProgramRaster },
+
+{"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
+
+{"rsnPathCreate",                    "(JIZJJF)J",                             (void*)nPathCreate },
+{"rsnMeshCreate",                    "(J[I[I[I)J",                            (void*)nMeshCreate },
+
+{"rsnMeshGetVertexBufferCount",      "(JJ)I",                                 (void*)nMeshGetVertexBufferCount },
+{"rsnMeshGetIndexCount",             "(JJ)I",                                 (void*)nMeshGetIndexCount },
+{"rsnMeshGetVertices",               "(JJ[II)V",                              (void*)nMeshGetVertices },
+{"rsnMeshGetIndices",                "(JJ[I[II)V",                            (void*)nMeshGetIndices },
+
+};
+
+static int registerFuncs(JNIEnv *_env)
+{
+    return android::AndroidRuntime::registerNativeMethods(
+            _env, classPathName, methods, NELEM(methods));
+}
+
+// ---------------------------------------------------------------------------
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        ALOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    if (registerFuncs(env) < 0) {
+        ALOGE("ERROR: Renderscript native registration failed\n");
+        goto bail;
+    }
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 96063d5..c14ed8b 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -656,12 +656,19 @@
         }
 
         @Override
-        public void setTime(long millis) {
+        public boolean setTime(long millis) {
             getContext().enforceCallingOrSelfPermission(
                     "android.permission.SET_TIME",
                     "setTime");
 
-            SystemClock.setCurrentTimeMillis(millis);
+            if (mNativeData == 0) {
+                Slog.w(TAG, "Not setting time since no alarm driver is available.");
+                return false;
+            }
+
+            synchronized (mLock) {
+                return setKernelTime(mNativeData, millis) == 0;
+            }
         }
 
         @Override
@@ -1039,6 +1046,7 @@
     private native void close(long nativeData);
     private native void set(long nativeData, int type, long seconds, long nanoseconds);
     private native int waitForAlarm(long nativeData);
+    private native int setKernelTime(long nativeData, long millis);
     private native int setKernelTimezone(long nativeData, int minuteswest);
 
     void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 3fb006b..fc4838c 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -114,12 +114,11 @@
 
     // Describes how bitmaps are placed in the atlas. Each bitmap is
     // represented by several entries in the array:
-    // int0: SkBitmap*, the native bitmap object
-    // int1: x position
-    // int2: y position
-    // int3: rotated, 1 if the bitmap must be rotated, 0 otherwise
-    // NOTE: This will need to be handled differently to support 64 bit pointers
-    private int[] mAtlasMap;
+    // long0: SkBitmap*, the native bitmap object
+    // long1: x position
+    // long2: y position
+    // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
+    private long[] mAtlasMap;
 
     /**
      * Creates a new service. Upon creating, the service will gather the list of
@@ -196,7 +195,7 @@
         private final ArrayList<Bitmap> mBitmaps;
         private final int mPixelCount;
 
-        private int mNativeBitmap;
+        private long mNativeBitmap;
 
         // Used for debugging only
         private Bitmap mAtlasBitmap;
@@ -260,8 +259,8 @@
 
             final Atlas.Entry entry = new Atlas.Entry();
 
-            mAtlasMap = new int[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
-            int[] atlasMap = mAtlasMap;
+            mAtlasMap = new long[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
+            long[] atlasMap = mAtlasMap;
             int mapIndex = 0;
 
             boolean result = false;
@@ -288,8 +287,7 @@
                         }
                         canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
                         canvas.restore();
-                        // TODO: Change mAtlasMap to long[] to support 64-bit systems
-                        atlasMap[mapIndex++] = (int) bitmap.mNativeBitmap;
+                        atlasMap[mapIndex++] = bitmap.mNativeBitmap;
                         atlasMap[mapIndex++] = entry.x;
                         atlasMap[mapIndex++] = entry.y;
                         atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
@@ -365,9 +363,9 @@
         }
     }
 
-    private static native int nAcquireAtlasCanvas(Canvas canvas, int width, int height);
-    private static native void nReleaseAtlasCanvas(Canvas canvas, int bitmap);
-    private static native boolean nUploadAtlas(GraphicBuffer buffer, int bitmap);
+    private static native long nAcquireAtlasCanvas(Canvas canvas, int width, int height);
+    private static native void nReleaseAtlasCanvas(Canvas canvas, long bitmap);
+    private static native boolean nUploadAtlas(GraphicBuffer buffer, long bitmap);
 
     @Override
     public boolean isCompatible(int ppid) {
@@ -380,7 +378,7 @@
     }
 
     @Override
-    public int[] getMap() throws RemoteException {
+    public long[] getMap() throws RemoteException {
         return mAtlasReady.get() ? mAtlasMap : null;
     }
 
diff --git a/services/core/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java
index 783dff1..583f1bc 100644
--- a/services/core/java/com/android/server/ConsumerIrService.java
+++ b/services/core/java/com/android/server/ConsumerIrService.java
@@ -49,13 +49,13 @@
 
     private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
 
-    private static native int halOpen();
-    private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern);
-    private static native int[] halGetCarrierFrequencies(int halObject);
+    private static native long halOpen();
+    private static native int halTransmit(long halObject, int carrierFrequency, int[] pattern);
+    private static native int[] halGetCarrierFrequencies(long halObject);
 
     private final Context mContext;
     private final PowerManager.WakeLock mWakeLock;
-    private final int mHal;
+    private final long mNativeHal;
     private final Object mHalLock = new Object();
 
     ConsumerIrService(Context context) {
@@ -65,23 +65,23 @@
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(true);
 
-        mHal = halOpen();
+        mNativeHal = halOpen();
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) {
-            if (mHal == 0) {
+            if (mNativeHal == 0) {
                 throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!");
             }
-        } else if (mHal != 0) {
+        } else if (mNativeHal != 0) {
             throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!");
         }
     }
 
     @Override
     public boolean hasIrEmitter() {
-        return mHal != 0;
+        return mNativeHal != 0;
     }
 
     private void throwIfNoIrEmitter() {
-        if (mHal == 0) {
+        if (mNativeHal == 0) {
             throw new UnsupportedOperationException("IR emitter not available");
         }
     }
@@ -111,7 +111,7 @@
 
         // Right now there is no mechanism to ensure fair queing of IR requests
         synchronized (mHalLock) {
-            int err = halTransmit(mHal, carrierFrequency, pattern);
+            int err = halTransmit(mNativeHal, carrierFrequency, pattern);
 
             if (err < 0) {
                 Slog.e(TAG, "Error transmitting: " + err);
@@ -129,7 +129,7 @@
         throwIfNoIrEmitter();
 
         synchronized(mHalLock) {
-            return halGetCarrierFrequencies(mHal);
+            return halGetCarrierFrequencies(mNativeHal);
         }
     }
 }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 816ae69..f73a92b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -91,6 +91,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -384,18 +385,37 @@
     }
 
     class ShutdownCallBack extends UnmountCallBack {
-        IMountShutdownObserver observer;
-        ShutdownCallBack(String path, IMountShutdownObserver observer) {
+        MountShutdownLatch mMountShutdownLatch;
+        ShutdownCallBack(String path, final MountShutdownLatch mountShutdownLatch) {
             super(path, true, false);
-            this.observer = observer;
+            mMountShutdownLatch = mountShutdownLatch;
         }
 
         @Override
         void handleFinished() {
             int ret = doUnmountVolume(path, true, removeEncryption);
-            if (observer != null) {
+            Slog.i(TAG, "Unmount completed: " + path + ", result code: " + ret);
+            mMountShutdownLatch.countDown();
+        }
+    }
+
+    static class MountShutdownLatch {
+        private IMountShutdownObserver mObserver;
+        private AtomicInteger mCount;
+
+        MountShutdownLatch(final IMountShutdownObserver observer, int count) {
+            mObserver = observer;
+            mCount = new AtomicInteger(count);
+        }
+
+        void countDown() {
+            boolean sendShutdown = false;
+            if (mCount.decrementAndGet() == 0) {
+                sendShutdown = true;
+            }
+            if (sendShutdown && mObserver != null) {
                 try {
-                    observer.onShutDownComplete(ret);
+                    mObserver.onShutDownComplete(StorageResultCode.OperationSucceeded);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "RemoteException when shutting down");
                 }
@@ -1426,6 +1446,10 @@
 
         Slog.i(TAG, "Shutting down");
         synchronized (mVolumesLock) {
+            // Get all volumes to be unmounted.
+            MountShutdownLatch mountShutdownLatch = new MountShutdownLatch(observer,
+                                                            mVolumeStates.size());
+
             for (String path : mVolumeStates.keySet()) {
                 String state = mVolumeStates.get(path);
 
@@ -1461,19 +1485,16 @@
 
                 if (state.equals(Environment.MEDIA_MOUNTED)) {
                     // Post a unmount message.
-                    ShutdownCallBack ucb = new ShutdownCallBack(path, observer);
+                    ShutdownCallBack ucb = new ShutdownCallBack(path, mountShutdownLatch);
                     mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
                 } else if (observer != null) {
                     /*
-                     * Observer is waiting for onShutDownComplete when we are done.
-                     * Since nothing will be done send notification directly so shutdown
-                     * sequence can continue.
+                     * Count down, since nothing will be done. The observer will be
+                     * notified when we are done so shutdown sequence can continue.
                      */
-                    try {
-                        observer.onShutDownComplete(StorageResultCode.OperationSucceeded);
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "RemoteException when shutting down");
-                    }
+                    mountShutdownLatch.countDown();
+                    Slog.i(TAG, "Unmount completed: " + path +
+                        ", result code: " + StorageResultCode.OperationSucceeded);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index ad7ec99..e6c5422 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -82,6 +82,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
@@ -1022,6 +1023,15 @@
         }
     }
 
+    private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
+        ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size());
+        for (InterfaceAddress ia : addresses) {
+            if (!ia.getAddress().isLinkLocalAddress())
+                filtered.add(ia);
+        }
+        return filtered;
+    }
+
     private void modifyNat(String action, String internalInterface, String externalInterface)
             throws SocketException {
         final Command cmd = new Command("nat", action, internalInterface, externalInterface);
@@ -1031,8 +1041,10 @@
         if (internalNetworkInterface == null) {
             cmd.appendArg("0");
         } else {
-            Collection<InterfaceAddress> interfaceAddresses = internalNetworkInterface
-                    .getInterfaceAddresses();
+            // Don't touch link-local routes, as link-local addresses aren't routable,
+            // kernel creates link-local routes on all interfaces automatically
+            List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
+                    internalNetworkInterface.getInterfaceAddresses());
             cmd.appendArg(interfaceAddresses.size());
             for (InterfaceAddress ia : interfaceAddresses) {
                 InetAddress addr = NetworkUtils.getNetworkPart(
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 699d79e..77f5182 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -37,6 +37,10 @@
 import android.telephony.SignalStrength;
 import android.telephony.CellInfo;
 import android.telephony.TelephonyManager;
+import android.telephony.DisconnectCause;
+import android.telephony.PreciseCallState;
+import android.telephony.PreciseDataConnectionState;
+import android.telephony.PreciseDisconnectCause;
 import android.text.TextUtils;
 import android.util.Slog;
 
@@ -125,6 +129,17 @@
 
     private List<CellInfo> mCellInfo = null;
 
+    private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+
+    private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+
+    private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+
+    private PreciseCallState mPreciseCallState = new PreciseCallState();
+
+    private PreciseDataConnectionState mPreciseDataConnectionState =
+                new PreciseDataConnectionState();
+
     static final int PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
                 PhoneStateListener.LISTEN_CALL_STATE |
@@ -132,6 +147,10 @@
                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
                 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
 
+    static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
+                PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
+                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
+
     private static final int MSG_USER_SWITCHED = 1;
 
     private final Handler mHandler = new Handler() {
@@ -305,6 +324,21 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
+                        try {
+                            r.callback.onPreciseCallStateChanged(mPreciseCallState);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
+                    if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
+                        try {
+                            r.callback.onPreciseDataConnectionStateChanged(
+                                    mPreciseDataConnectionState);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -533,30 +567,47 @@
                 }
                 handleRemoveListLocked();
             }
+            mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
+                    apnType, apn, reason, linkProperties, "");
+            for (Record r : mRecords) {
+                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
+                    try {
+                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
         }
         broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
                 apnType, linkProperties, linkCapabilities, roaming);
+        broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
+                linkProperties, "");
     }
 
     public void notifyDataConnectionFailed(String reason, String apnType) {
         if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
             return;
         }
-        /*
-         * This is commented out because there is no onDataConnectionFailed callback
-         * in PhoneStateListener. There should be.
         synchronized (mRecords) {
-            mDataConnectionFailedReason = reason;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
-                Record r = mRecords.get(i);
-                if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
-                    // XXX
+            mPreciseDataConnectionState = new PreciseDataConnectionState(
+                    TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                    apnType, "", reason, null, "");
+            for (Record r : mRecords) {
+                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
+                    try {
+                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
                 }
             }
+            handleRemoveListLocked();
         }
-        */
         broadcastDataConnectionFailed(reason, apnType);
+        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
     }
 
     public void notifyCellLocation(Bundle cellLocation) {
@@ -602,6 +653,81 @@
         }
     }
 
+    public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
+            int backgroundCallState) {
+        if (!checkNotifyPermission("notifyPreciseCallState()")) {
+            return;
+        }
+        synchronized (mRecords) {
+            mRingingCallState = ringingCallState;
+            mForegroundCallState = foregroundCallState;
+            mBackgroundCallState = backgroundCallState;
+            mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
+                    backgroundCallState,
+                    DisconnectCause.NOT_VALID,
+                    PreciseDisconnectCause.NOT_VALID);
+            for (Record r : mRecords) {
+                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
+                    try {
+                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
+                DisconnectCause.NOT_VALID,
+                PreciseDisconnectCause.NOT_VALID);
+    }
+
+    public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
+        if (!checkNotifyPermission("notifyDisconnectCause()")) {
+            return;
+        }
+        synchronized (mRecords) {
+            mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
+                    mBackgroundCallState, disconnectCause, preciseDisconnectCause);
+            for (Record r : mRecords) {
+                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
+                    try {
+                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+        broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
+                mBackgroundCallState, disconnectCause, preciseDisconnectCause);
+    }
+
+    public void notifyPreciseDataConnectionFailed(String reason, String apnType,
+            String apn, String failCause) {
+        if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
+            return;
+        }
+        synchronized (mRecords) {
+            mPreciseDataConnectionState = new PreciseDataConnectionState(
+                    TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                    apnType, apn, reason, null, failCause);
+            for (Record r : mRecords) {
+                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
+                    try {
+                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -738,6 +864,33 @@
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
+            int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
+        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
+        intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
+        intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
+        intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
+        intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
+        intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
+    }
+
+    private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
+            String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) {
+        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
+        intent.putExtra(PhoneConstants.STATE_KEY, state);
+        intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
+        if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
+        if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
+        if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
+        if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
+        if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
+
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
+    }
+
     private boolean checkNotifyPermission(String method) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
                 == PackageManager.PERMISSION_GRANTED) {
@@ -766,6 +919,12 @@
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_PHONE_STATE, null);
         }
+
+        if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+
+        }
     }
 
     private void handleRemoveListLocked() {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
old mode 100644
new mode 100755
index 17bb3e0..d66c5a7
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -203,6 +203,7 @@
                     Slog.i(TAG, "Waited long enough for: " + r);
                     mStartingBackground.remove(i);
                     N--;
+                    i--;
                 }
             }
             while (mDelayedStartList.size() > 0
diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java
index 88a2207..eb7a383 100644
--- a/services/core/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/core/java/com/android/server/firewall/IntentFirewall.java
@@ -270,11 +270,13 @@
         }
 
         File[] files = rulesDir.listFiles();
-        for (int i=0; i<files.length; i++) {
-            File file = files[i];
+        if (files != null) {
+            for (int i=0; i<files.length; i++) {
+                File file = files[i];
 
-            if (file.getName().endsWith(".xml")) {
-                readRules(file, resolvers);
+                if (file.getName().endsWith(".xml")) {
+                    readRules(file, resolvers);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 62c0ec9..94cf668 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -78,6 +78,7 @@
             synchronized (this) {
                 if (mColor == 0 && !mFlashing) {
                     setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
+                    mColor = 0;
                     mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
                 }
             }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 6185e50..ad6eabd 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -221,6 +221,17 @@
         return execute(builder.toString());
     }
 
+    public int idmap(String targetApkPath, String overlayApkPath, int uid) {
+        StringBuilder builder = new StringBuilder("idmap");
+        builder.append(' ');
+        builder.append(targetApkPath);
+        builder.append(' ');
+        builder.append(overlayApkPath);
+        builder.append(' ');
+        builder.append(uid);
+        return execute(builder.toString());
+    }
+
     public int movedex(String srcPath, String dstPath) {
         StringBuilder builder = new StringBuilder("movedex");
         builder.append(' ');
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index da0c38d..70eee7e 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -219,6 +219,7 @@
     static final int SCAN_UPDATE_TIME = 1<<6;
     static final int SCAN_DEFER_DEX = 1<<7;
     static final int SCAN_BOOTING = 1<<8;
+    static final int SCAN_TRUSTED_OVERLAY = 1<<9;
 
     static final int REMOVE_CHATTY = 1<<16;
 
@@ -259,9 +260,15 @@
 
     private static final String LIB_DIR_NAME = "lib";
 
+    private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
+
     static final String mTempContainerPrefix = "smdl2tmp";
 
     final ServiceThread mHandlerThread;
+
+    private static final String IDMAP_PREFIX = "/data/resource-cache/";
+    private static final String IDMAP_SUFFIX = "@idmap";
+
     final PackageHandler mHandler;
 
     final int mSdkVersion = Build.VERSION.SDK_INT;
@@ -297,6 +304,9 @@
     // This is the object monitoring the system app dir.
     final FileObserver mVendorInstallObserver;
 
+    // This is the object monitoring the vendor overlay package dir.
+    final FileObserver mVendorOverlayInstallObserver;
+
     // This is the object monitoring mAppInstallDir.
     final FileObserver mAppInstallObserver;
 
@@ -344,6 +354,10 @@
     final HashMap<String, PackageParser.Package> mPackages =
             new HashMap<String, PackageParser.Package>();
 
+    // Tracks available target package names -> overlay package paths.
+    final HashMap<String, HashMap<String, PackageParser.Package>> mOverlays =
+        new HashMap<String, HashMap<String, PackageParser.Package>>();
+
     final Settings mSettings;
     boolean mRestoredSettings;
 
@@ -1279,6 +1293,17 @@
                 }
             }
 
+            // Collect vendor overlay packages.
+            // (Do this before scanning any apps.)
+            // For security and version matching reason, only consider
+            // overlay packages if they reside in VENDOR_OVERLAY_DIR.
+            File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
+            mVendorOverlayInstallObserver = new AppDirObserver(
+                vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
+            mVendorOverlayInstallObserver.startWatching();
+            scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
+                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0);
+
             // Find base frameworks (resource packages without code).
             mFrameworkInstallObserver = new AppDirObserver(
                 frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
@@ -1307,6 +1332,11 @@
 
             // Collect all vendor packages.
             File vendorAppDir = new File("/vendor/app");
+            try {
+                vendorAppDir = vendorAppDir.getCanonicalFile();
+            } catch (IOException e) {
+                // failed to look up canonical path, continue with original one
+            }
             mVendorInstallObserver = new AppDirObserver(
                 vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
             mVendorInstallObserver.startWatching();
@@ -3502,6 +3532,56 @@
         return finalList;
     }
 
+    private void createIdmapsForPackageLI(PackageParser.Package pkg) {
+        HashMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName);
+        if (overlays == null) {
+            Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages");
+            return;
+        }
+        for (PackageParser.Package opkg : overlays.values()) {
+            // Not much to do if idmap fails: we already logged the error
+            // and we certainly don't want to abort installation of pkg simply
+            // because an overlay didn't fit properly. For these reasons,
+            // ignore the return value of createIdmapForPackagePairLI.
+            createIdmapForPackagePairLI(pkg, opkg);
+        }
+    }
+
+    private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
+            PackageParser.Package opkg) {
+        if (!opkg.mTrustedOverlay) {
+            Slog.w(TAG, "Skipping target and overlay pair " + pkg.mScanPath + " and " +
+                    opkg.mScanPath + ": overlay not trusted");
+            return false;
+        }
+        HashMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
+        if (overlaySet == null) {
+            Slog.e(TAG, "was about to create idmap for " + pkg.mScanPath + " and " +
+                    opkg.mScanPath + " but target package has no known overlays");
+            return false;
+        }
+        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+        if (mInstaller.idmap(pkg.mScanPath, opkg.mScanPath, sharedGid) != 0) {
+            Slog.e(TAG, "Failed to generate idmap for " + pkg.mScanPath + " and " + opkg.mScanPath);
+            return false;
+        }
+        PackageParser.Package[] overlayArray =
+            overlaySet.values().toArray(new PackageParser.Package[0]);
+        Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
+            public int compare(PackageParser.Package p1, PackageParser.Package p2) {
+                return p1.mOverlayPriority - p2.mOverlayPriority;
+            }
+        };
+        Arrays.sort(overlayArray, cmp);
+
+        pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
+        int i = 0;
+        for (PackageParser.Package p : overlayArray) {
+            pkg.applicationInfo.resourceDirs[i++] = p.applicationInfo.sourceDir;
+        }
+        return true;
+    }
+
     private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
         String[] files = dir.list();
         if (files == null) {
@@ -3599,7 +3679,7 @@
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setOnlyCoreApps(mOnlyCore);
         final PackageParser.Package pkg = pp.parsePackage(scanFile,
-                scanPath, mMetrics, parseFlags);
+                scanPath, mMetrics, parseFlags, (scanMode & SCAN_TRUSTED_OVERLAY) != 0);
 
         if (pkg == null) {
             mLastScanError = pp.getParseError();
@@ -3627,6 +3707,7 @@
             updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
             if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
         }
+        boolean updatedPkgBetter = false;
         // First check if this is a system package that may involve an update
         if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             if (ps != null && !ps.codePath.equals(scanFile)) {
@@ -3681,6 +3762,7 @@
                     synchronized (mPackages) {
                         mSettings.enableSystemPackageLPw(ps.name);
                     }
+                    updatedPkgBetter = true;
                 }
             }
         }
@@ -3757,7 +3839,7 @@
 
         String codePath = null;
         String resPath = null;
-        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
+        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
             if (ps != null && ps.resourcePathString != null) {
                 resPath = ps.resourcePathString;
             } else {
@@ -5108,6 +5190,29 @@
             }
 
             pkgSetting.setTimeStamp(scanFileTime);
+
+            // Create idmap files for pairs of (packages, overlay packages).
+            // Note: "android", ie framework-res.apk, is handled by native layers.
+            if (pkg.mOverlayTarget != null) {
+                // This is an overlay package.
+                if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
+                    if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
+                        mOverlays.put(pkg.mOverlayTarget,
+                                new HashMap<String, PackageParser.Package>());
+                    }
+                    HashMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
+                    map.put(pkg.packageName, pkg);
+                    PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
+                    if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
+                        mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
+                        return null;
+                    }
+                }
+            } else if (mOverlays.containsKey(pkg.packageName) &&
+                    !pkg.packageName.equals("android")) {
+                // This is a regular package, with one or more known overlay packages.
+                createIdmapsForPackageLI(pkg);
+            }
         }
 
         return pkg;
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 342515b..c26a516 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -36,6 +36,7 @@
 #include <unistd.h>
 #include <linux/ioctl.h>
 #include <linux/android_alarm.h>
+#include <linux/rtc.h>
 
 namespace android {
 
@@ -58,6 +59,7 @@
     virtual ~AlarmImpl();
 
     virtual int set(int type, struct timespec *ts) = 0;
+    virtual int setTime(struct timeval *tv) = 0;
     virtual int waitForAlarm() = 0;
 
 protected:
@@ -71,6 +73,7 @@
     AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
 
     int set(int type, struct timespec *ts);
+    int setTime(struct timeval *tv);
     int waitForAlarm();
 };
 
@@ -82,6 +85,7 @@
     ~AlarmImplTimerFd();
 
     int set(int type, struct timespec *ts);
+    int setTime(struct timeval *tv);
     int waitForAlarm();
 
 private:
@@ -107,6 +111,19 @@
     return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
 }
 
+int AlarmImplAlarmDriver::setTime(struct timeval *tv)
+{
+    struct timespec ts;
+    int res;
+
+    ts.tv_sec = tv->tv_sec;
+    ts.tv_nsec = tv->tv_usec * 1000;
+    res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
+    if (res < 0)
+        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
+    return res;
+}
+
 int AlarmImplAlarmDriver::waitForAlarm()
 {
     return ioctl(fds[0], ANDROID_ALARM_WAIT);
@@ -140,6 +157,50 @@
     return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
 }
 
+int AlarmImplTimerFd::setTime(struct timeval *tv)
+{
+    struct rtc_time rtc;
+    struct tm tm, *gmtime_res;
+    int fd;
+    int res;
+
+    res = settimeofday(tv, NULL);
+    if (res < 0) {
+        ALOGV("settimeofday() failed: %s\n", strerror(errno));
+        return -1;
+    }
+
+    fd = open("/dev/rtc0", O_RDWR);
+    if (fd < 0) {
+        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
+        return res;
+    }
+
+    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
+    if (!gmtime_res) {
+        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
+        res = -1;
+        goto done;
+    }
+
+    memset(&rtc, 0, sizeof(rtc));
+    rtc.tm_sec = tm.tm_sec;
+    rtc.tm_min = tm.tm_min;
+    rtc.tm_hour = tm.tm_hour;
+    rtc.tm_mday = tm.tm_mday;
+    rtc.tm_mon = tm.tm_mon;
+    rtc.tm_year = tm.tm_year;
+    rtc.tm_wday = tm.tm_wday;
+    rtc.tm_yday = tm.tm_yday;
+    rtc.tm_isdst = tm.tm_isdst;
+    res = ioctl(fd, RTC_SET_TIME, &rtc);
+    if (res < 0)
+        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
+done:
+    close(fd);
+    return res;
+}
+
 int AlarmImplTimerFd::waitForAlarm()
 {
     epoll_event events[N_ANDROID_TIMERFDS];
@@ -168,6 +229,30 @@
     return result;
 }
 
+static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
+{
+    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
+    struct timeval tv;
+    int ret;
+
+    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
+        return -1;
+    }
+
+    tv.tv_sec = (time_t) (millis / 1000LL);
+    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
+
+    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
+
+    ret = impl->setTime(&tv);
+
+    if(ret < 0) {
+        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
+        ret = -1;
+    }
+    return ret;
+}
+
 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
 {
     struct timezone tz;
@@ -309,6 +394,7 @@
     {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
     {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
     {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
+    {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
     {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
 };
 
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 4a1b55d..163692b 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -73,7 +73,7 @@
     SkSafeUnref(previousCanvas);
 }
 
-static SkBitmap* com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
+static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
         jobject canvas, jint width, jint height) {
 
     SkBitmap* bitmap = new SkBitmap;
@@ -84,12 +84,13 @@
     SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (*bitmap));
     swapCanvasPtr(env, canvas, nativeCanvas);
 
-    return bitmap;
+    return reinterpret_cast<jlong>(bitmap);
 }
 
 static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject,
-        jobject canvas, SkBitmap* bitmap) {
+        jobject canvas, jlong bitmapHandle) {
 
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     SkCanvas* nativeCanvas = SkNEW(SkCanvas);
     swapCanvasPtr(env, canvas, nativeCanvas);
 
@@ -108,21 +109,22 @@
     return result;
 
 static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
-        jobject graphicBuffer, SkBitmap* bitmap) {
+        jobject graphicBuffer, jlong bitmapHandle) {
 
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     // The goal of this method is to copy the bitmap into the GraphicBuffer
     // using the GPU to swizzle the texture content
     sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
 
     if (buffer != NULL) {
         EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        if (display == EGL_NO_DISPLAY) return false;
+        if (display == EGL_NO_DISPLAY) return JNI_FALSE;
 
         EGLint major;
         EGLint minor;
         if (!eglInitialize(display, &major, &minor)) {
             ALOGW("Could not initialize EGL");
-            return false;
+            return JNI_FALSE;
         }
 
         // We're going to use a 1x1 pbuffer surface later on
@@ -143,13 +145,13 @@
             ALOGW("Could not select EGL configuration");
             eglReleaseThread();
             eglTerminate(display);
-            return false;
+            return JNI_FALSE;
         }
         if (configCount <= 0) {
             ALOGW("Could not find EGL configuration");
             eglReleaseThread();
             eglTerminate(display);
-            return false;
+            return JNI_FALSE;
         }
 
         // These objects are initialized below but the default "null"
@@ -164,7 +166,7 @@
         EGLContext context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, attrs);
         if (context == EGL_NO_CONTEXT) {
             ALOGW("Could not create EGL context");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // Create the 1x1 pbuffer
@@ -172,12 +174,12 @@
         surface = eglCreatePbufferSurface(display, configs[0], surfaceAttrs);
         if (surface == EGL_NO_SURFACE) {
             ALOGW("Could not create EGL surface");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         if (!eglMakeCurrent(display, surface, surface, context)) {
             ALOGW("Could not change current EGL context");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // We use an EGLImage to access the content of the GraphicBuffer
@@ -188,7 +190,7 @@
                 EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
         if (image == EGL_NO_IMAGE_KHR) {
             ALOGW("Could not create EGL image");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         glGenTextures(1, &texture);
@@ -196,7 +198,7 @@
         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
         if (glGetError() != GL_NO_ERROR) {
             ALOGW("Could not create/bind texture");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // Upload the content of the bitmap in the GraphicBuffer
@@ -205,7 +207,7 @@
                 GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
         if (glGetError() != GL_NO_ERROR) {
             ALOGW("Could not upload to texture");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // The fence is used to wait for the texture upload to finish
@@ -214,7 +216,7 @@
         fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
         if (fence == EGL_NO_SYNC_KHR) {
             ALOGW("Could not create sync fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
@@ -223,13 +225,13 @@
                 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
         if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
             ALOGW("Failed to wait for the fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
-        CLEANUP_GL_AND_RETURN(true);
+        CLEANUP_GL_AND_RETURN(JNI_TRUE);
     }
 
-    return false;
+    return JNI_FALSE;
 }
 
 // ----------------------------------------------------------------------------
@@ -247,11 +249,11 @@
 const char* const kClassPathName = "com/android/server/AssetAtlasService";
 
 static JNINativeMethod gMethods[] = {
-    { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)I",
+    { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J",
             (void*) com_android_server_AssetAtlasService_acquireCanvas },
-    { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;I)V",
+    { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V",
             (void*) com_android_server_AssetAtlasService_releaseCanvas },
-    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;I)Z",
+    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z",
             (void*) com_android_server_AssetAtlasService_upload },
 };
 
diff --git a/services/core/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp
index 004c0aa..3a50ff7 100644
--- a/services/core/jni/com_android_server_ConsumerIrService.cpp
+++ b/services/core/jni/com_android_server_ConsumerIrService.cpp
@@ -29,7 +29,7 @@
 
 namespace android {
 
-static jint halOpen(JNIEnv *env, jobject obj) {
+static jlong halOpen(JNIEnv *env, jobject obj) {
     hw_module_t const* module;
     consumerir_device_t *dev;
     int err;
@@ -47,10 +47,10 @@
         return 0;
     }
 
-    return reinterpret_cast<jint>(dev);
+    return reinterpret_cast<jlong>(dev);
 }
 
-static jint halTransmit(JNIEnv *env, jobject obj, jint halObject,
+static jint halTransmit(JNIEnv *env, jobject obj, jlong halObject,
    jint carrierFrequency, jintArray pattern) {
     int ret;
 
@@ -67,8 +67,8 @@
 }
 
 static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj,
-    jint halObject) {
-    consumerir_device_t *dev = (consumerir_device_t *) halObject;
+    jlong halObject) {
+    consumerir_device_t *dev = reinterpret_cast<consumerir_device_t*>(halObject);
     consumerir_freq_range_t *ranges;
     int len;
 
@@ -101,9 +101,9 @@
 }
 
 static JNINativeMethod method_table[] = {
-    { "halOpen", "()I", (void *)halOpen },
-    { "halTransmit", "(II[I)I", (void *)halTransmit },
-    { "halGetCarrierFrequencies", "(I)[I", (void *)halGetCarrierFrequencies},
+    { "halOpen", "()J", (void *)halOpen },
+    { "halTransmit", "(JI[I)I", (void *)halTransmit },
+    { "halGetCarrierFrequencies", "(J)[I", (void *)halGetCarrierFrequencies},
 };
 
 int register_android_server_ConsumerIrService(JNIEnv *env) {
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index f1fa6cf..fc6de60 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -163,8 +163,10 @@
         return NULL;
 
     int fd = usb_device_get_fd(device);
-    if (fd < 0)
+    if (fd < 0) {
+        usb_device_close(device);
         return NULL;
+    }
     int newFD = dup(fd);
     usb_device_close(device);
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index db40cbe..b498c0c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -165,7 +165,7 @@
         // had to fallback to a different runtime because it is
         // running as root and we need to be the system user to set
         // the property. http://b/11463182
-        SystemProperties.set("persist.sys.dalvik.vm.lib", VMRuntime.getRuntime().vmLibrary());
+        SystemProperties.set("persist.sys.dalvik.vm.lib.1", VMRuntime.getRuntime().vmLibrary());
 
         // Enable the sampling profiler.
         if (SamplingProfilerIntegration.isEnabled()) {
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
new file mode 100644
index 0000000..323e0ac
--- /dev/null
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.telephony;
+
+/**
+ * Contains disconnect call causes generated by the
+ * framework and the RIL.
+ *
+ * @hide
+ */
+public class DisconnectCause {
+
+    /** The disconnect cause is not valid (Not received a disconnect cause) */
+    public static final int NOT_VALID                      = -1;
+    /** Has not yet disconnected */
+    public static final int NOT_DISCONNECTED               = 0;
+    /** An incoming call that was missed and never answered */
+    public static final int INCOMING_MISSED                = 1;
+    /** Normal; Remote hangup*/
+    public static final int NORMAL                         = 2;
+    /** Normal; Local hangup */
+    public static final int LOCAL                          = 3;
+    /** Outgoing call to busy line */
+    public static final int BUSY                           = 4;
+    /** Outgoing call to congested network */
+    public static final int CONGESTION                     = 5;
+    /** Not presently used */
+    public static final int MMI                            = 6;
+    /** Invalid dial string */
+    public static final int INVALID_NUMBER                 = 7;
+    /** Cannot reach the peer */
+    public static final int NUMBER_UNREACHABLE             = 8;
+    /** Cannot reach the server */
+    public static final int SERVER_UNREACHABLE             = 9;
+    /** Invalid credentials */
+    public static final int INVALID_CREDENTIALS            = 10;
+    /** Calling from out of network is not allowed */
+    public static final int OUT_OF_NETWORK                 = 11;
+    /** Server error */
+    public static final int SERVER_ERROR                   = 12;
+    /** Client timed out */
+    public static final int TIMED_OUT                      = 13;
+    /** Client went out of network range */
+    public static final int LOST_SIGNAL                    = 14;
+    /** GSM or CDMA ACM limit exceeded */
+    public static final int LIMIT_EXCEEDED                 = 15;
+    /** An incoming call that was rejected */
+    public static final int INCOMING_REJECTED              = 16;
+    /** Radio is turned off explicitly */
+    public static final int POWER_OFF                      = 17;
+    /** Out of service */
+    public static final int OUT_OF_SERVICE                 = 18;
+    /** No ICC, ICC locked, or other ICC error */
+    public static final int ICC_ERROR                      = 19;
+    /** Call was blocked by call barring */
+    public static final int CALL_BARRED                    = 20;
+    /** Call was blocked by fixed dial number */
+    public static final int FDN_BLOCKED                    = 21;
+    /** Call was blocked by restricted all voice access */
+    public static final int CS_RESTRICTED                  = 22;
+    /** Call was blocked by restricted normal voice access */
+    public static final int CS_RESTRICTED_NORMAL           = 23;
+    /** Call was blocked by restricted emergency voice access */
+    public static final int CS_RESTRICTED_EMERGENCY        = 24;
+    /** Unassigned number */
+    public static final int UNOBTAINABLE_NUMBER            = 25;
+    /** MS is locked until next power cycle */
+    public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE  = 26;
+    /** Drop call*/
+    public static final int CDMA_DROP                      = 27;
+    /** INTERCEPT order received, MS state idle entered */
+    public static final int CDMA_INTERCEPT                 = 28;
+    /** MS has been redirected, call is cancelled */
+    public static final int CDMA_REORDER                   = 29;
+    /** Service option rejection */
+    public static final int CDMA_SO_REJECT                 = 30;
+    /** Requested service is rejected, retry delay is set */
+    public static final int CDMA_RETRY_ORDER               = 31;
+    /** Unable to obtain access to the CDMA system */
+    public static final int CDMA_ACCESS_FAILURE            = 32;
+    /** Not a preempted call */
+    public static final int CDMA_PREEMPTED                 = 33;
+    /** Not an emergency call */
+    public static final int CDMA_NOT_EMERGENCY             = 34;
+    /** Access Blocked by CDMA network */
+    public static final int CDMA_ACCESS_BLOCKED            = 35;
+    /** Unknown error or not specified */
+    public static final int ERROR_UNSPECIFIED              = 36;
+
+    /** Private constructor to avoid class instantiation. */
+    private DisconnectCause() {
+        // Do nothing.
+    }
+}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index ff77fc0..538548d 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -24,6 +24,8 @@
 import android.telephony.CellLocation;
 import android.telephony.CellInfo;
 import android.telephony.Rlog;
+import android.telephony.PreciseCallState;
+import android.telephony.PreciseDataConnectionState;
 
 import com.android.internal.telephony.IPhoneStateListener;
 
@@ -165,6 +167,27 @@
      */
     public static final int LISTEN_CELL_INFO = 0x00000400;
 
+    /**
+     * Listen for precise changes and fails to the device calls (cellular).
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+     * READ_PRECISE_PHONE_STATE}
+     *
+     * @hide
+     */
+    public static final int LISTEN_PRECISE_CALL_STATE                       = 0x00000800;
+
+    /**
+     * Listen for precise changes and fails on the data connection (cellular).
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+     * READ_PRECISE_PHONE_STATE}
+     *
+     * @see #onPreciseDataConnectionStateChanged
+     * @hide
+     */
+    public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE            = 0x00001000;
+
     public PhoneStateListener() {
     }
 
@@ -293,6 +316,25 @@
     }
 
     /**
+     * Callback invoked when precise device call state changes.
+     *
+     * @hide
+     */
+    public void onPreciseCallStateChanged(PreciseCallState callState) {
+        // default implementation empty
+    }
+
+    /**
+     * Callback invoked when data connection state changes with precise information.
+     *
+     * @hide
+     */
+    public void onPreciseDataConnectionStateChanged(
+            PreciseDataConnectionState dataConnectionState) {
+        // default implementation empty
+    }
+
+    /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
      */
@@ -344,6 +386,16 @@
         public void onCellInfoChanged(List<CellInfo> cellInfo) {
             Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0, cellInfo).sendToTarget();
         }
+
+        public void onPreciseCallStateChanged(PreciseCallState callState) {
+            Message.obtain(mHandler, LISTEN_PRECISE_CALL_STATE, 0, 0, callState).sendToTarget();
+        }
+
+        public void onPreciseDataConnectionStateChanged(
+                PreciseDataConnectionState dataConnectionState) {
+            Message.obtain(mHandler, LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0,
+                    dataConnectionState).sendToTarget();
+        }
     };
 
     Handler mHandler = new Handler() {
@@ -383,6 +435,12 @@
                     break;
                 case LISTEN_CELL_INFO:
                     PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
+                    break;
+                case LISTEN_PRECISE_CALL_STATE:
+                    PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
+                    break;
+                case LISTEN_PRECISE_DATA_CONNECTION_STATE:
+                    PhoneStateListener.this.onPreciseDataConnectionStateChanged((PreciseDataConnectionState)msg.obj);
             }
         }
     };
diff --git a/telephony/java/android/telephony/PreciseCallState.aidl b/telephony/java/android/telephony/PreciseCallState.aidl
new file mode 100644
index 0000000..447f29b
--- /dev/null
+++ b/telephony/java/android/telephony/PreciseCallState.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2014, 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.
+*/
+
+package android.telephony;
+
+parcelable PreciseCallState;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
new file mode 100644
index 0000000..a85df15
--- /dev/null
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Rlog;
+import android.telephony.DisconnectCause;
+import android.telephony.PreciseDisconnectCause;
+
+/**
+ * Contains precise call state and call fail causes generated by the
+ * framework and the RIL.
+ *
+ * The following call information is included in returned PreciseCallState:
+ *
+ * <ul>
+ *   <li>Ringing call state.
+ *   <li>Foreground call state.
+ *   <li>Background call state.
+ *   <li>Disconnect cause; generated by the framework.
+ *   <li>Precise disconnect cause; generated by the RIL.
+ * </ul>
+ *
+ * @hide
+ */
+public class PreciseCallState implements Parcelable {
+
+    /** Call state is not valid (Not received a call state). */
+    public static final int PRECISE_CALL_STATE_NOT_VALID =      -1;
+    /** Call state: No activity. */
+    public static final int PRECISE_CALL_STATE_IDLE =           0;
+    /** Call state: Active. */
+    public static final int PRECISE_CALL_STATE_ACTIVE =         1;
+    /** Call state: On hold. */
+    public static final int PRECISE_CALL_STATE_HOLDING =        2;
+    /** Call state: Dialing. */
+    public static final int PRECISE_CALL_STATE_DIALING =        3;
+    /** Call state: Alerting. */
+    public static final int PRECISE_CALL_STATE_ALERTING =       4;
+    /** Call state: Incoming. */
+    public static final int PRECISE_CALL_STATE_INCOMING =       5;
+    /** Call state: Waiting. */
+    public static final int PRECISE_CALL_STATE_WAITING =        6;
+    /** Call state: Disconnected. */
+    public static final int PRECISE_CALL_STATE_DISCONNECTED =   7;
+    /** Call state: Disconnecting. */
+    public static final int PRECISE_CALL_STATE_DISCONNECTING =  8;
+
+    private int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
+    private int mDisconnectCause = DisconnectCause.NOT_VALID;
+    private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public PreciseCallState(int ringingCall, int foregroundCall, int backgroundCall,
+            int disconnectCause, int preciseDisconnectCause) {
+        mRingingCallState = ringingCall;
+        mForegroundCallState = foregroundCall;
+        mBackgroundCallState = backgroundCall;
+        mDisconnectCause = disconnectCause;
+        mPreciseDisconnectCause = preciseDisconnectCause;
+    }
+
+    /**
+     * Empty Constructor
+     *
+     * @hide
+     */
+    public PreciseCallState() {
+    }
+
+    /**
+     * Construct a PreciseCallState object from the given parcel.
+     */
+    private PreciseCallState(Parcel in) {
+        mRingingCallState = in.readInt();
+        mForegroundCallState = in.readInt();
+        mBackgroundCallState = in.readInt();
+        mDisconnectCause = in.readInt();
+        mPreciseDisconnectCause = in.readInt();
+    }
+
+    /**
+     * Get precise ringing call state
+     *
+     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
+     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
+     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
+     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
+     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
+     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
+     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     */
+    public int getRingingCallState() {
+        return mRingingCallState;
+    }
+
+    /**
+     * Get precise foreground call state
+     *
+     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
+     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
+     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
+     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
+     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
+     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
+     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     */
+    public int getForegroundCallState() {
+        return mForegroundCallState;
+    }
+
+    /**
+     * Get precise background call state
+     *
+     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
+     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
+     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
+     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
+     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
+     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
+     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     */
+    public int getBackgroundCallState() {
+        return mBackgroundCallState;
+    }
+
+    /**
+     * Get disconnect cause generated by the framework
+     *
+     * @see DisconnectCause#NOT_VALID
+     * @see DisconnectCause#NOT_DISCONNECTED
+     * @see DisconnectCause#INCOMING_MISSED
+     * @see DisconnectCause#NORMAL
+     * @see DisconnectCause#LOCAL
+     * @see DisconnectCause#BUSY
+     * @see DisconnectCause#CONGESTION
+     * @see DisconnectCause#MMI
+     * @see DisconnectCause#INVALID_NUMBER
+     * @see DisconnectCause#NUMBER_UNREACHABLE
+     * @see DisconnectCause#SERVER_UNREACHABLE
+     * @see DisconnectCause#INVALID_CREDENTIALS
+     * @see DisconnectCause#OUT_OF_NETWORK
+     * @see DisconnectCause#SERVER_ERROR
+     * @see DisconnectCause#TIMED_OUT
+     * @see DisconnectCause#LOST_SIGNAL
+     * @see DisconnectCause#LIMIT_EXCEEDED
+     * @see DisconnectCause#INCOMING_REJECTED
+     * @see DisconnectCause#POWER_OFF
+     * @see DisconnectCause#OUT_OF_SERVICE
+     * @see DisconnectCause#ICC_ERROR
+     * @see DisconnectCause#CALL_BARRED
+     * @see DisconnectCause#FDN_BLOCKED
+     * @see DisconnectCause#CS_RESTRICTED
+     * @see DisconnectCause#CS_RESTRICTED_NORMAL
+     * @see DisconnectCause#CS_RESTRICTED_EMERGENCY
+     * @see DisconnectCause#UNOBTAINABLE_NUMBER
+     * @see DisconnectCause#CDMA_LOCKED_UNTIL_POWER_CYCLE
+     * @see DisconnectCause#CDMA_DROP
+     * @see DisconnectCause#CDMA_INTERCEPT
+     * @see DisconnectCause#CDMA_REORDER
+     * @see DisconnectCause#CDMA_SO_REJECT
+     * @see DisconnectCause#CDMA_RETRY_ORDER
+     * @see DisconnectCause#CDMA_ACCESS_FAILURE
+     * @see DisconnectCause#CDMA_PREEMPTED
+     * @see DisconnectCause#CDMA_NOT_EMERGENCY
+     * @see DisconnectCause#CDMA_ACCESS_BLOCKED
+     * @see DisconnectCause#ERROR_UNSPECIFIED
+     */
+    public int getDisconnectCause() {
+        return mDisconnectCause;
+    }
+
+    /**
+     * Get disconnect cause generated by the RIL
+     *
+     * @see PreciseDisconnectCause#NOT_VALID
+     * @see PreciseDisconnectCause#NO_DISCONNECT_CAUSE_AVAILABLE
+     * @see PreciseDisconnectCause#UNOBTAINABLE_NUMBER
+     * @see PreciseDisconnectCause#NORMAL
+     * @see PreciseDisconnectCause#BUSY
+     * @see PreciseDisconnectCause#NUMBER_CHANGED
+     * @see PreciseDisconnectCause#STATUS_ENQUIRY
+     * @see PreciseDisconnectCause#NORMAL_UNSPECIFIED
+     * @see PreciseDisconnectCause#NO_CIRCUIT_AVAIL
+     * @see PreciseDisconnectCause#TEMPORARY_FAILURE
+     * @see PreciseDisconnectCause#SWITCHING_CONGESTION
+     * @see PreciseDisconnectCause#CHANNEL_NOT_AVAIL
+     * @see PreciseDisconnectCause#QOS_NOT_AVAIL
+     * @see PreciseDisconnectCause#BEARER_NOT_AVAIL
+     * @see PreciseDisconnectCause#ACM_LIMIT_EXCEEDED
+     * @see PreciseDisconnectCause#CALL_BARRED
+     * @see PreciseDisconnectCause#FDN_BLOCKED
+     * @see PreciseDisconnectCause#IMSI_UNKNOWN_IN_VLR
+     * @see PreciseDisconnectCause#IMEI_NOT_ACCEPTED
+     * @see PreciseDisconnectCause#CDMA_LOCKED_UNTIL_POWER_CYCLE
+     * @see PreciseDisconnectCause#CDMA_DROP
+     * @see PreciseDisconnectCause#CDMA_INTERCEPT
+     * @see PreciseDisconnectCause#CDMA_REORDER
+     * @see PreciseDisconnectCause#CDMA_SO_REJECT
+     * @see PreciseDisconnectCause#CDMA_RETRY_ORDER
+     * @see PreciseDisconnectCause#CDMA_ACCESS_FAILURE
+     * @see PreciseDisconnectCause#CDMA_PREEMPTED
+     * @see PreciseDisconnectCause#CDMA_NOT_EMERGENCY
+     * @see PreciseDisconnectCause#CDMA_ACCESS_BLOCKED
+     * @see PreciseDisconnectCause#ERROR_UNSPECIFIED
+     */
+    public int getPreciseDisconnectCause() {
+        return mPreciseDisconnectCause;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mRingingCallState);
+        out.writeInt(mForegroundCallState);
+        out.writeInt(mBackgroundCallState);
+        out.writeInt(mDisconnectCause);
+        out.writeInt(mPreciseDisconnectCause);
+    }
+
+    public static final Parcelable.Creator<PreciseCallState> CREATOR
+            = new Parcelable.Creator<PreciseCallState>() {
+
+        public PreciseCallState createFromParcel(Parcel in) {
+            return new PreciseCallState(in);
+        }
+
+        public PreciseCallState[] newArray(int size) {
+            return new PreciseCallState[size];
+        }
+    };
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + mRingingCallState;
+        result = prime * result + mForegroundCallState;
+        result = prime * result + mBackgroundCallState;
+        result = prime * result + mDisconnectCause;
+        result = prime * result + mPreciseDisconnectCause;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        PreciseCallState other = (PreciseCallState) obj;
+        return (mRingingCallState != other.mRingingCallState &&
+            mForegroundCallState != other.mForegroundCallState &&
+            mBackgroundCallState != other.mBackgroundCallState &&
+            mDisconnectCause != other.mDisconnectCause &&
+            mPreciseDisconnectCause != other.mPreciseDisconnectCause);
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("Ringing call state: " + mRingingCallState);
+        sb.append(", Foreground call state: " + mForegroundCallState);
+        sb.append(", Background call state: " + mBackgroundCallState);
+        sb.append(", Disconnect cause: " + mDisconnectCause);
+        sb.append(", Precise disconnect cause: " + mPreciseDisconnectCause);
+
+        return sb.toString();
+    }
+}
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.aidl b/telephony/java/android/telephony/PreciseDataConnectionState.aidl
new file mode 100644
index 0000000..07ad762
--- /dev/null
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2014, 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.
+*/
+
+package android.telephony;
+
+parcelable PreciseDataConnectionState;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
new file mode 100644
index 0000000..87529fe
--- /dev/null
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Rlog;
+import android.telephony.TelephonyManager;
+import android.net.LinkProperties;
+
+/**
+ * Contains precise data connection state.
+ *
+ * The following data connection information is included in returned PreciseDataConnectionState:
+ *
+ * <ul>
+ *   <li>Data connection state.
+ *   <li>Network type of the connection.
+ *   <li>APN type.
+ *   <li>APN.
+ *   <li>Data connection change reason.
+ *   <li>The properties of the network link.
+ *   <li>Data connection fail cause.
+ * </ul>
+ *
+ * @hide
+ */
+public class PreciseDataConnectionState implements Parcelable {
+
+    private int mState = TelephonyManager.DATA_UNKNOWN;
+    private int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+    private String mAPNType = "";
+    private String mAPN = "";
+    private String mReason = "";
+    private LinkProperties mLinkProperties = null;
+    private String mFailCause = "";
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public PreciseDataConnectionState(int state, int networkType,
+            String apnType, String apn, String reason,
+            LinkProperties linkProperties, String failCause) {
+        mState = state;
+        mNetworkType = networkType;
+        mAPNType = apnType;
+        mAPN = apn;
+        mReason = reason;
+        mLinkProperties = linkProperties;
+        mFailCause = failCause;
+    }
+
+    /**
+     * Empty Constructor
+     *
+     * @hide
+     */
+    public PreciseDataConnectionState() {
+    }
+
+    /**
+     * Construct a PreciseDataConnectionState object from the given parcel.
+     */
+    private PreciseDataConnectionState(Parcel in) {
+        mState = in.readInt();
+        mNetworkType = in.readInt();
+        mAPNType = in.readString();
+        mAPN = in.readString();
+        mReason = in.readString();
+        mLinkProperties = (LinkProperties)in.readParcelable(null);
+        mFailCause = in.readString();
+    }
+
+    /**
+     * Get data connection state
+     *
+     * @see TelephonyManager#DATA_UNKNOWN
+     * @see TelephonyManager#DATA_DISCONNECTED
+     * @see TelephonyManager#DATA_CONNECTING
+     * @see TelephonyManager#DATA_CONNECTED
+     * @see TelephonyManager#DATA_SUSPENDED
+     */
+    public int getDataConnectionState() {
+        return mState;
+    }
+
+    /**
+     * Get data connection network type
+     *
+     * @see TelephonyManager#NETWORK_TYPE_UNKNOWN
+     * @see TelephonyManager#NETWORK_TYPE_GPRS
+     * @see TelephonyManager#NETWORK_TYPE_EDGE
+     * @see TelephonyManager#NETWORK_TYPE_UMTS
+     * @see TelephonyManager#NETWORK_TYPE_CDMA
+     * @see TelephonyManager#NETWORK_TYPE_EVDO_0
+     * @see TelephonyManager#NETWORK_TYPE_EVDO_A
+     * @see TelephonyManager#NETWORK_TYPE_1xRTT
+     * @see TelephonyManager#NETWORK_TYPE_HSDPA
+     * @see TelephonyManager#NETWORK_TYPE_HSUPA
+     * @see TelephonyManager#NETWORK_TYPE_HSPA
+     * @see TelephonyManager#NETWORK_TYPE_IDEN
+     * @see TelephonyManager#NETWORK_TYPE_EVDO_B
+     * @see TelephonyManager#NETWORK_TYPE_LTE
+     * @see TelephonyManager#NETWORK_TYPE_EHRPD
+     * @see TelephonyManager#NETWORK_TYPE_HSPAP
+     */
+    public int getDataConnectionNetworkType() {
+        return mNetworkType;
+    }
+
+    /**
+     * Get data connection APN type
+     */
+    public String getDataConnectionAPNType() {
+        return mAPNType;
+    }
+
+    /**
+     * Get data connection APN.
+     */
+    public String getDataConnectionAPN() {
+        return mAPN;
+    }
+
+    /**
+     * Get data connection change reason.
+     */
+    public String getDataConnectionChangeReason() {
+        return mReason;
+    }
+
+    /**
+     * Get the properties of the network link.
+     */
+    public LinkProperties getDataConnectionLinkProperties() {
+        return mLinkProperties;
+    }
+
+    /**
+     * Get data connection fail cause, in case there was a failure.
+     */
+    public String getDataConnectionFailCause() {
+        return mFailCause;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mState);
+        out.writeInt(mNetworkType);
+        out.writeString(mAPNType);
+        out.writeString(mAPN);
+        out.writeString(mReason);
+        out.writeParcelable(mLinkProperties, flags);
+        out.writeString(mFailCause);
+    }
+
+    public static final Parcelable.Creator<PreciseDataConnectionState> CREATOR
+            = new Parcelable.Creator<PreciseDataConnectionState>() {
+
+        public PreciseDataConnectionState createFromParcel(Parcel in) {
+            return new PreciseDataConnectionState(in);
+        }
+
+        public PreciseDataConnectionState[] newArray(int size) {
+            return new PreciseDataConnectionState[size];
+        }
+    };
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + mState;
+        result = prime * result + mNetworkType;
+        result = prime * result + ((mAPNType == null) ? 0 : mAPNType.hashCode());
+        result = prime * result + ((mAPN == null) ? 0 : mAPN.hashCode());
+        result = prime * result + ((mReason == null) ? 0 : mReason.hashCode());
+        result = prime * result + ((mLinkProperties == null) ? 0 : mLinkProperties.hashCode());
+        result = prime * result + ((mFailCause == null) ? 0 : mFailCause.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        PreciseDataConnectionState other = (PreciseDataConnectionState) obj;
+        if (mAPN == null) {
+            if (other.mAPN != null) {
+                return false;
+            }
+        } else if (!mAPN.equals(other.mAPN)) {
+            return false;
+        }
+        if (mAPNType == null) {
+            if (other.mAPNType != null) {
+                return false;
+            }
+        } else if (!mAPNType.equals(other.mAPNType)) {
+            return false;
+        }
+        if (mFailCause == null) {
+            if (other.mFailCause != null) {
+                return false;
+            }
+        } else if (!mFailCause.equals(other.mFailCause)) {
+            return false;
+        }
+        if (mLinkProperties == null) {
+            if (other.mLinkProperties != null) {
+                return false;
+            }
+        } else if (!mLinkProperties.equals(other.mLinkProperties)) {
+            return false;
+        }
+        if (mNetworkType != other.mNetworkType) {
+            return false;
+        }
+        if (mReason == null) {
+            if (other.mReason != null) {
+                return false;
+            }
+        } else if (!mReason.equals(other.mReason)) {
+            return false;
+        }
+        if (mState != other.mState) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("Data Connection state: " + mState);
+        sb.append(", Network type: " + mNetworkType);
+        sb.append(", APN type: " + mAPNType);
+        sb.append(", APN: " + mAPN);
+        sb.append(", Change reason: " + mReason);
+        sb.append(", Link properties: " + mLinkProperties);
+        sb.append(", Fail cause: " + mFailCause);
+
+        return sb.toString();
+    }
+}
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
new file mode 100644
index 0000000..54ab19d
--- /dev/null
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.telephony;
+
+/**
+ * Contains precise disconnect call causes generated by the
+ * framework and the RIL.
+ *
+ * @hide
+ */
+public class PreciseDisconnectCause {
+
+    /** The disconnect cause is not valid (Not received a disconnect cause)*/
+    public static final int NOT_VALID                      = -1;
+    /** No disconnect cause provided. Generally a local disconnect or an incoming missed call */
+    public static final int NO_DISCONNECT_CAUSE_AVAILABLE  = 0;
+    /**
+     * The destination cannot be reached because the number, although valid,
+     * is not currently assigned
+     */
+    public static final int UNOBTAINABLE_NUMBER            = 1;
+    /** One of the users involved in the call has requested that the call is cleared */
+    public static final int NORMAL                         = 16;
+    /** The called user is unable to accept another call */
+    public static final int BUSY                           = 17;
+    /** The called number is no longer assigned */
+    public static final int NUMBER_CHANGED                 = 22;
+    /** Provided in response to a STATUS ENQUIRY message */
+    public static final int STATUS_ENQUIRY                 = 30;
+    /** Reports a normal disconnect only when no other normal cause applies */
+    public static final int NORMAL_UNSPECIFIED             = 31;
+    /** There is no channel presently available to handle the call */
+    public static final int NO_CIRCUIT_AVAIL               = 34;
+    /**
+     * The network is not functioning correctly and the condition is not likely to last
+     * a long period of time
+     */
+    public static final int TEMPORARY_FAILURE              = 41;
+    /** The switching equipment is experiencing a period of high traffic */
+    public static final int SWITCHING_CONGESTION           = 42;
+    /** The channel cannot be provided */
+    public static final int CHANNEL_NOT_AVAIL              = 44;
+    /** The requested quality of service (ITU-T X.213) cannot be provided */
+    public static final int QOS_NOT_AVAIL                  = 49;
+    /** The requested bearer capability is not available at this time */
+    public static final int BEARER_NOT_AVAIL               = 58;
+    /** The call clearing is due to ACM being greater than or equal to ACMmax */
+    public static final int ACM_LIMIT_EXCEEDED             = 68;
+    /** The call is restricted */
+    public static final int CALL_BARRED                    = 240;
+    /** The call is blocked by the Fixed Dialing Number list */
+    public static final int FDN_BLOCKED                    = 241;
+    /** The given IMSI is not known at the VLR */
+    /** TS 24.008 cause 4 */
+    public static final int IMSI_UNKNOWN_IN_VLR            = 242;
+    /**
+     * The network does not accept emergency call establishment using an IMEI or not accept attach
+     * procedure for emergency services using an IMEI
+     */
+    public static final int IMEI_NOT_ACCEPTED              = 243;
+    /** MS is locked until next power cycle */
+    public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE  = 1000;
+    /** Drop call*/
+    public static final int CDMA_DROP                      = 1001;
+    /** INTERCEPT order received, MS state idle entered */
+    public static final int CDMA_INTERCEPT                 = 1002;
+    /** MS has been redirected, call is cancelled */
+    public static final int CDMA_REORDER                   = 1003;
+    /** Service option rejection */
+    public static final int CDMA_SO_REJECT                 = 1004;
+    /** Requested service is rejected, retry delay is set */
+    public static final int CDMA_RETRY_ORDER               = 1005;
+    /** Unable to obtain access to the CDMA system */
+    public static final int CDMA_ACCESS_FAILURE            = 1006;
+    /** Not a preempted call */
+    public static final int CDMA_PREEMPTED                 = 1007;
+    /** Not an emergency call */
+    public static final int CDMA_NOT_EMERGENCY             = 1008;
+    /** Access Blocked by CDMA network */
+    public static final int CDMA_ACCESS_BLOCKED            = 1009;
+    /** Disconnected due to unspecified reasons */
+    public static final int ERROR_UNSPECIFIED              = 0xffff;
+
+    /** Private constructor to avoid class instantiation. */
+    private PreciseDisconnectCause() {
+        // Do nothing.
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8f17e72..ea22bc4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -211,6 +211,267 @@
      */
     public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
 
+    /**
+     * Broadcast intent action indicating that a precise call state
+     * (cellular) on the device has changed.
+     *
+     * <p>
+     * The {@link #EXTRA_RINGING_CALL_STATE} extra indicates the ringing call state.
+     * The {@link #EXTRA_FOREGROUND_CALL_STATE} extra indicates the foreground call state.
+     * The {@link #EXTRA_BACKGROUND_CALL_STATE} extra indicates the background call state.
+     * The {@link #EXTRA_DISCONNECT_CAUSE} extra indicates the disconnect cause.
+     * The {@link #EXTRA_PRECISE_DISCONNECT_CAUSE} extra indicates the precise disconnect cause.
+     *
+     * <p class="note">
+     * Requires the READ_PRECISE_PHONE_STATE permission.
+     *
+     * @see #EXTRA_RINGING_CALL_STATE
+     * @see #EXTRA_FOREGROUND_CALL_STATE
+     * @see #EXTRA_BACKGROUND_CALL_STATE
+     * @see #EXTRA_DISCONNECT_CAUSE
+     * @see #EXTRA_PRECISE_DISCONNECT_CAUSE
+     *
+     * <p class="note">
+     * Requires the READ_PRECISE_PHONE_STATE permission.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PRECISE_CALL_STATE_CHANGED =
+            "android.intent.action.PRECISE_CALL_STATE";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
+     * for an integer containing the state of the current ringing call.
+     *
+     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
+     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
+     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
+     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
+     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
+     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
+     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_RINGING_CALL_STATE = "ringing_state";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
+     * for an integer containing the state of the current foreground call.
+     *
+     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
+     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
+     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
+     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
+     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
+     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
+     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_FOREGROUND_CALL_STATE = "foreground_state";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
+     * for an integer containing the state of the current background call.
+     *
+     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
+     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
+     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
+     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
+     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
+     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
+     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
+     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_BACKGROUND_CALL_STATE = "background_state";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
+     * for an integer containing the disconnect cause.
+     *
+     * @see DisconnectCause
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DISCONNECT_CAUSE = "disconnect_cause";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast
+     * for an integer containing the disconnect cause provided by the RIL.
+     *
+     * @see PreciseDisconnectCause
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_PRECISE_DISCONNECT_CAUSE = "precise_disconnect_cause";
+
+    /**
+     * Broadcast intent action indicating a data connection has changed,
+     * providing precise information about the connection.
+     *
+     * <p>
+     * The {@link #EXTRA_DATA_STATE} extra indicates the connection state.
+     * The {@link #EXTRA_DATA_NETWORK_TYPE} extra indicates the connection network type.
+     * The {@link #EXTRA_DATA_APN_TYPE} extra indicates the APN type.
+     * The {@link #EXTRA_DATA_APN} extra indicates the APN.
+     * The {@link #EXTRA_DATA_CHANGE_REASON} extra indicates the connection change reason.
+     * The {@link #EXTRA_DATA_IFACE_PROPERTIES} extra indicates the connection interface.
+     * The {@link #EXTRA_DATA_FAILURE_CAUSE} extra indicates the connection fail cause.
+     *
+     * <p class="note">
+     * Requires the READ_PRECISE_PHONE_STATE permission.
+     *
+     * @see #EXTRA_DATA_STATE
+     * @see #EXTRA_DATA_NETWORK_TYPE
+     * @see #EXTRA_DATA_APN_TYPE
+     * @see #EXTRA_DATA_APN
+     * @see #EXTRA_DATA_CHANGE_REASON
+     * @see #EXTRA_DATA_IFACE
+     * @see #EXTRA_DATA_FAILURE_CAUSE
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
+            "android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for an integer containing the state of the current data connection.
+     *
+     * @see TelephonyManager#DATA_UNKNOWN
+     * @see TelephonyManager#DATA_DISCONNECTED
+     * @see TelephonyManager#DATA_CONNECTING
+     * @see TelephonyManager#DATA_CONNECTED
+     * @see TelephonyManager#DATA_SUSPENDED
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_STATE = PhoneConstants.STATE_KEY;
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for an integer containing the network type.
+     *
+     * @see TelephonyManager#NETWORK_TYPE_UNKNOWN
+     * @see TelephonyManager#NETWORK_TYPE_GPRS
+     * @see TelephonyManager#NETWORK_TYPE_EDGE
+     * @see TelephonyManager#NETWORK_TYPE_UMTS
+     * @see TelephonyManager#NETWORK_TYPE_CDMA
+     * @see TelephonyManager#NETWORK_TYPE_EVDO_0
+     * @see TelephonyManager#NETWORK_TYPE_EVDO_A
+     * @see TelephonyManager#NETWORK_TYPE_1xRTT
+     * @see TelephonyManager#NETWORK_TYPE_HSDPA
+     * @see TelephonyManager#NETWORK_TYPE_HSUPA
+     * @see TelephonyManager#NETWORK_TYPE_HSPA
+     * @see TelephonyManager#NETWORK_TYPE_IDEN
+     * @see TelephonyManager#NETWORK_TYPE_EVDO_B
+     * @see TelephonyManager#NETWORK_TYPE_LTE
+     * @see TelephonyManager#NETWORK_TYPE_EHRPD
+     * @see TelephonyManager#NETWORK_TYPE_HSPAP
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_NETWORK_TYPE = PhoneConstants.DATA_NETWORK_TYPE_KEY;
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for an String containing the data APN type.
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getStringExtra(String name)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_APN_TYPE = PhoneConstants.DATA_APN_TYPE_KEY;
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for an String containing the data APN.
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getStringExtra(String name)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_APN = PhoneConstants.DATA_APN_KEY;
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for an String representation of the change reason.
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getStringExtra(String name)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_CHANGE_REASON = PhoneConstants.STATE_CHANGE_REASON_KEY;
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for an String representation of the data interface.
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getParcelableExtra(String name)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_LINK_PROPERTIES_KEY = PhoneConstants.DATA_LINK_PROPERTIES_KEY;
+
+    /**
+     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
+     * for the data connection fail cause.
+     *
+     * <p class="note">
+     * Retrieve with
+     * {@link android.content.Intent#getStringExtra(String name)}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY;
 
     //
     //
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 4be11b8..59bdf64 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -97,6 +97,7 @@
     public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37;
     public static final int CMD_IS_PROVISIONING_APN = BASE + 38;
     public static final int EVENT_PROVISIONING_APN_ALARM = BASE + 39;
+    public static final int CMD_NET_STAT_POLL = BASE + 40;
 
     /***** Constants *****/
 
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 3a04ceb..f228d4e 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -20,6 +20,8 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.CellInfo;
+import android.telephony.PreciseCallState;
+import android.telephony.PreciseDataConnectionState;
 
 oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
@@ -35,5 +37,7 @@
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
     void onOtaspChanged(in int otaspMode);
     void onCellInfoChanged(in List<CellInfo> cellInfo);
+    void onPreciseCallStateChanged(in PreciseCallState callState);
+    void onPreciseDataConnectionStateChanged(in PreciseDataConnectionState dataConnectionState);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 59c8472..546ce17 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -41,4 +41,9 @@
     void notifyCellLocation(in Bundle cellLocation);
     void notifyOtaspChanged(in int otaspMode);
     void notifyCellInfo(in List<CellInfo> cellInfo);
+    void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
+            int backgroundCallState);
+    void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
+    void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
+            String failCause);
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 4163255..1fed417d 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -73,6 +73,8 @@
     public static final String PHONE_NAME_KEY = "phoneName";
     public static final String FAILURE_REASON_KEY = "reason";
     public static final String STATE_CHANGE_REASON_KEY = "reason";
+    public static final String DATA_NETWORK_TYPE_KEY = "networkType";
+    public static final String DATA_FAILURE_CAUSE_KEY = "failCause";
     public static final String DATA_APN_TYPE_KEY = "apnType";
     public static final String DATA_APN_KEY = "apn";
     public static final String DATA_LINK_PROPERTIES_KEY = "linkProperties";
diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk
new file mode 100644
index 0000000..64ea63c
--- /dev/null
+++ b/tests/SystemUIDemoModeController/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := DemoModeController
+
+include $(BUILD_PACKAGE)
diff --git a/tests/SystemUIDemoModeController/AndroidManifest.xml b/tests/SystemUIDemoModeController/AndroidManifest.xml
new file mode 100644
index 0000000..2e97932
--- /dev/null
+++ b/tests/SystemUIDemoModeController/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.demomodecontroller"
+    android:versionCode="1"
+    android:versionName="0.1" >
+
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="false"
+        android:label="@string/app_name" >
+        <activity
+            android:name=".DemoModeController" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/tests/SystemUIDemoModeController/res/values/strings.xml b/tests/SystemUIDemoModeController/res/values/strings.xml
new file mode 100644
index 0000000..257a353
--- /dev/null
+++ b/tests/SystemUIDemoModeController/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<resources>
+
+    <string name="app_name">Demo Mode Controller</string>
+    <string name="help_text">"Drag: control icon states\nLong-press + drag: control background color\nDouble-tap: toggle bar mode</string>
+
+</resources>
diff --git a/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java b/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java
new file mode 100644
index 0000000..b177d7e
--- /dev/null
+++ b/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.example.android.demomodecontroller;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+public class DemoModeController extends Activity implements OnTouchListener {
+    private static final String TAG = DemoModeController.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private final Context mContext = this;
+    private final Handler mHandler = new Handler();
+    private final PointF mLastDown = new PointF();
+
+    private View mContent;
+    private Handler mBackground;
+    private int mTouchSlop;
+    private long mLastDownTime;
+    private boolean mControllingColor;
+    private Toast mToast;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS  // so WM gives us enough room
+                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+        getActionBar().hide();
+        mContent = new View(mContext);
+        mContent.setBackgroundColor(0xff33b5e5);
+        mContent.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+        mContent.setOnTouchListener(this);
+        setContentView(mContent);
+        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+
+        final HandlerThread background = new HandlerThread("background");
+        background.start();
+        mBackground = new Handler(background.getLooper());
+        updateMode();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        exitDemoMode();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        exitDemoMode();
+        mToast = Toast.makeText(mContext, R.string.help_text, Toast.LENGTH_LONG);
+        mToast.show();
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        if (mToast != null) {
+            mToast.cancel();
+            mToast = null;
+        }
+        final int action = event.getAction();
+        if (action == MotionEvent.ACTION_DOWN) {
+            if (DEBUG) Log.d(TAG, "down");
+            mHandler.postDelayed(mLongPressCheck, 500);
+            final long now = SystemClock.uptimeMillis();
+            if (now - mLastDownTime < 200) {
+                toggleMode();
+            }
+            mLastDownTime = now;
+            mLastDown.x = event.getX();
+            mLastDown.y = event.getY();
+            return true;
+        }
+        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+            if (DEBUG) Log.d(TAG, "upOrCancel");
+            mControllingColor = false;
+            mHandler.removeCallbacks(mLongPressCheck);
+        }
+        if (action != MotionEvent.ACTION_MOVE) return false;
+
+        float x = event.getX();
+        float y = event.getY();
+        if (Math.abs(mLastDown.x - x) > mTouchSlop || Math.abs(mLastDown.y - y) > mTouchSlop) {
+            mHandler.removeCallbacks(mLongPressCheck);
+        }
+        x = Math.max(x, 0);
+        y = Math.max(y, 0);
+        final int h = mContent.getMeasuredHeight();
+        final int w = mContent.getMeasuredWidth();
+        x = Math.min(x, w);
+        y = Math.min(y, h);
+
+        y = h - y;
+        x = w - x;
+
+        if (mControllingColor) {
+            final float hue = y / (h / 360);
+            final float sat = 1 - (x / (float)w);
+            final float val = x / (float)w;
+            final int color = Color.HSVToColor(new float[]{hue, sat, val});
+            if (DEBUG) Log.d(TAG, String.format("hsv=(%s,%s,%s) argb=#%08x", hue, sat, val, color));
+            mContent.setBackgroundColor(color);
+            return true;
+        }
+
+        final int hh = (int)x / (w / 12);
+        if (hh != mHH) {
+            mHH = hh;
+            mBackground.removeCallbacks(mUpdateClock);
+            mBackground.post(mUpdateClock);
+        }
+
+        final int mm = (int)y / (h / 60);
+        if (mm != mMM) {
+            mMM = mm;
+            mBackground.removeCallbacks(mUpdateClock);
+            mBackground.post(mUpdateClock);
+        }
+
+        final int batteryLevel = (int)y / (h / 101);
+        if (batteryLevel != mBatteryLevel) {
+            mBatteryLevel = batteryLevel;
+            mBackground.removeCallbacks(mUpdateBattery);
+            mBackground.post(mUpdateBattery);
+        }
+
+        final boolean batteryPlugged = x >= w / 2;
+        if (batteryPlugged != mBatteryPlugged) {
+            mBatteryPlugged = batteryPlugged;
+            mBackground.removeCallbacks(mUpdateBattery);
+            mBackground.post(mUpdateBattery);
+        }
+
+        final int mobileLevel = (int)y / (h / 10);
+        if (mobileLevel != mMobileLevel) {
+            mMobileLevel = mobileLevel;
+            mBackground.removeCallbacks(mUpdateMobile);
+            mBackground.post(mUpdateMobile);
+        }
+
+        final int wifiLevel = (int)y / (h / 10);
+        if (wifiLevel != mWifiLevel) {
+            mWifiLevel = wifiLevel;
+            mBackground.removeCallbacks(mUpdateWifi);
+            mBackground.post(mUpdateWifi);
+        }
+
+        final int statusSlots = (int)x / (w / 13);
+        if (statusSlots != mStatusSlots) {
+            mStatusSlots = statusSlots;
+            mBackground.removeCallbacks(mUpdateStatus);
+            mBackground.post(mUpdateStatus);
+        }
+
+        final int networkIcons = (int)x / (w / 4);
+        if (networkIcons != mNetworkIcons) {
+            mNetworkIcons = networkIcons;
+            mBackground.removeCallbacks(mUpdateNetwork);
+            mBackground.post(mUpdateNetwork);
+        }
+
+        final int mobileDataType = (int)y / (h / 9);
+        if (mobileDataType != mMobileDataType) {
+            mMobileDataType = mobileDataType;
+            mBackground.removeCallbacks(mUpdateMobile);
+            mBackground.post(mUpdateMobile);
+        }
+        return true;
+    }
+
+    private void toggleMode() {
+        if (DEBUG) Log.d(TAG, "toggleMode");
+        mBarMode = (mBarMode + 1) % 3;
+        updateMode();
+    }
+
+    private void updateMode() {
+        mBackground.removeCallbacks(mUpdateBarMode);
+        mBackground.post(mUpdateBarMode);
+    }
+
+    private final Runnable mLongPressCheck = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(TAG, "mControllingColor = true");
+            mControllingColor = true;
+
+        }
+    };
+
+    private void exitDemoMode() {
+        if (DEBUG) Log.d(TAG, "exitDemoMode");
+        final Intent intent = new Intent("com.android.systemui.demo");
+        intent.putExtra("command", "exit");
+        mContext.sendBroadcast(intent);
+    }
+
+    private int mStatusSlots; // 0 - 12
+    private final Runnable mUpdateStatus = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "status");
+            intent.putExtra("volume", mStatusSlots < 1 ? "hide"
+                    : mStatusSlots < 2 ? "silent" : "vibrate");
+            intent.putExtra("bluetooth", mStatusSlots < 3 ? "hide"
+                    : mStatusSlots < 4 ? "disconnected" : "connected");
+            intent.putExtra("location", mStatusSlots < 5 ? "hide" : "show");
+            intent.putExtra("alarm", mStatusSlots < 6 ? "hide" : "show");
+            intent.putExtra("sync", mStatusSlots < 7 ? "hide" : "show");
+            intent.putExtra("tty", mStatusSlots < 8 ? "hide" : "show");
+            intent.putExtra("eri", mStatusSlots < 9 ? "hide" : "show");
+            intent.putExtra("secure", mStatusSlots < 10 ? "hide" : "show");
+            intent.putExtra("mute", mStatusSlots < 11 ? "hide" : "show");
+            intent.putExtra("speakerphone", mStatusSlots < 12 ? "hide" : "show");
+            mContext.sendBroadcast(intent);
+        }
+    };
+
+    private int mNetworkIcons;  // 0:airplane  1:mobile  2:airplane+wifi  3:mobile+wifi
+    private final Runnable mUpdateNetwork = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "network");
+            intent.putExtra("airplane", mNetworkIcons % 2 == 0 ? "show" : "hide");
+            intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide");
+            intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide");
+            mContext.sendBroadcast(intent);
+        }
+    };
+
+    private int mWifiLevel; // 0 - 4, 5 - 9, fully
+    private final Runnable mUpdateWifi = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "network");
+            intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide");
+            intent.putExtra("level", Integer.toString(mWifiLevel % 5));
+            intent.putExtra("fully", Boolean.toString(mWifiLevel > 4));
+            mContext.sendBroadcast(intent);
+        }
+    };
+
+    private int mMobileLevel; // 0 - 4, 5 - 9, fully
+    private int mMobileDataType; // 0 - 8
+    private static final String getDataType(int dataType) {
+        if (dataType == 1) return "1x";
+        if (dataType == 2) return "3g";
+        if (dataType == 3) return "4g";
+        if (dataType == 4) return "e";
+        if (dataType == 5) return "g";
+        if (dataType == 6) return "h";
+        if (dataType == 7) return "lte";
+        if (dataType == 8) return "roam";
+        return "";
+    }
+    private final Runnable mUpdateMobile = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "network");
+            intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide");
+            intent.putExtra("level", Integer.toString(mMobileLevel % 5));
+            intent.putExtra("fully", Boolean.toString(mMobileLevel > 4));
+            intent.putExtra("datatype", getDataType(mMobileDataType));
+            mContext.sendBroadcast(intent);
+        }
+    };
+
+    private boolean mBatteryPlugged;
+    private int mBatteryLevel; // 0 - 100
+    private final Runnable mUpdateBattery = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "battery");
+            intent.putExtra("level", Integer.toString(mBatteryLevel));
+            intent.putExtra("plugged", Boolean.toString(mBatteryPlugged));
+            mContext.sendBroadcast(intent);
+        }
+    };
+
+    private int mHH; // 0 - 11
+    private int mMM; // 0 - 59
+    private final Runnable mUpdateClock = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "clock");
+            intent.putExtra("hhmm", String.format("%02d%02d", mHH + 1, mMM));
+            mContext.sendBroadcast(intent);
+        }
+    };
+
+    private int mBarMode; // 0 - 2  (opaque, semi-transparent, translucent)
+    private final Runnable mUpdateBarMode = new Runnable() {
+        @Override
+        public void run() {
+            final Intent intent = new Intent("com.android.systemui.demo");
+            intent.putExtra("command", "bars");
+            intent.putExtra("mode", mBarMode == 1 ? "semi-transparent"
+                    : mBarMode == 2 ? "translucent" : "opaque");
+            mContext.sendBroadcast(intent);
+        }
+    };
+}
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 62200d9..5c11054 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -149,205 +149,506 @@
 // =========================================================================
 // =========================================================================
 
-status_t
-AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
+/* static */ void AaptLocaleValue::splitAndLowerCase(const char* const chars,
+        Vector<String8>* parts, const char separator) {
+    const char *p = chars;
+    const char *q;
+    while (NULL != (q = strchr(p, separator))) {
+         String8 val(p, q - p);
+         val.toLower();
+         parts->add(val);
+         p = q+1;
+    }
+
+    if (p < chars + strlen(chars)) {
+        String8 val(p);
+        val.toLower();
+        parts->add(val);
+    }
+}
+
+/* static */
+inline bool isAlpha(const String8& string) {
+     const size_t length = string.length();
+     for (size_t i = 0; i < length; ++i) {
+          if (!isalpha(string[i])) {
+              return false;
+          }
+     }
+
+     return true;
+}
+
+/* static */
+inline bool isNumber(const String8& string) {
+     const size_t length = string.length();
+     for (size_t i = 0; i < length; ++i) {
+          if (!isdigit(string[i])) {
+              return false;
+          }
+     }
+
+     return true;
+}
+
+void AaptLocaleValue::setLanguage(const char* languageChars) {
+     size_t i = 0;
+     while ((*languageChars) != '\0') {
+          language[i++] = tolower(*languageChars);
+          languageChars++;
+     }
+}
+
+void AaptLocaleValue::setRegion(const char* regionChars) {
+    size_t i = 0;
+    while ((*regionChars) != '\0') {
+         region[i++] = toupper(*regionChars);
+         regionChars++;
+    }
+}
+
+void AaptLocaleValue::setScript(const char* scriptChars) {
+    size_t i = 0;
+    while ((*scriptChars) != '\0') {
+         if (i == 0) {
+             script[i++] = toupper(*scriptChars);
+         } else {
+             script[i++] = tolower(*scriptChars);
+         }
+         scriptChars++;
+    }
+}
+
+void AaptLocaleValue::setVariant(const char* variantChars) {
+     size_t i = 0;
+     while ((*variantChars) != '\0') {
+          variant[i++] = *variantChars;
+          variantChars++;
+     }
+}
+
+bool AaptLocaleValue::initFromFilterString(const String8& str) {
+     // A locale (as specified in the filter) is an underscore separated name such
+     // as "en_US", "en_Latn_US", or "en_US_POSIX".
+     Vector<String8> parts;
+     splitAndLowerCase(str.string(), &parts, '_');
+
+     const int numTags = parts.size();
+     bool valid = false;
+     if (numTags >= 1) {
+         const String8& lang = parts[0];
+         if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
+             setLanguage(lang.string());
+             valid = true;
+         }
+     }
+
+     if (!valid || numTags == 1) {
+         return valid;
+     }
+
+     // At this point, valid == true && numTags > 1.
+     const String8& part2 = parts[1];
+     if ((part2.length() == 2 && isAlpha(part2)) ||
+         (part2.length() == 3 && isNumber(part2))) {
+         setRegion(part2.string());
+     } else if (part2.length() == 4 && isAlpha(part2)) {
+         setScript(part2.string());
+     } else if (part2.length() >= 5 && part2.length() <= 8) {
+         setVariant(part2.string());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags == 2) {
+         return valid;
+     }
+
+     // At this point, valid == true && numTags > 1.
+     const String8& part3 = parts[2];
+     if (((part3.length() == 2 && isAlpha(part3)) ||
+         (part3.length() == 3 && isNumber(part3))) && script[0]) {
+         setRegion(part3.string());
+     } else if (part3.length() >= 5 && part3.length() <= 8) {
+         setVariant(part3.string());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags == 3) {
+         return valid;
+     }
+
+     const String8& part4 = parts[3];
+     if (part4.length() >= 5 && part4.length() <= 8) {
+         setVariant(part4.string());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags > 4) {
+         return false;
+     }
+
+     return true;
+}
+
+int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
+    const int size = parts.size();
+    int currentIndex = startIndex;
+
+    String8 part = parts[currentIndex];
+    if (part[0] == 'b' && part[1] == '+') {
+        // This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
+        // except that the separator is "+" and not "-".
+        Vector<String8> subtags;
+        AaptLocaleValue::splitAndLowerCase(part.string(), &subtags, '+');
+        subtags.removeItemsAt(0);
+        if (subtags.size() == 1) {
+            setLanguage(subtags[0]);
+        } else if (subtags.size() == 2) {
+            setLanguage(subtags[0]);
+
+            // The second tag can either be a region, a variant or a script.
+            switch (subtags[1].size()) {
+                case 2:
+                case 3:
+                    setRegion(subtags[1]);
+                    break;
+                case 4:
+                    setScript(subtags[1]);
+                    break;
+                case 5:
+                case 6:
+                case 7:
+                case 8:
+                    setVariant(subtags[1]);
+                    break;
+                default:
+                    fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n",
+                            part.string());
+                    return -1;
+            }
+        } else if (subtags.size() == 3) {
+            // The language is always the first subtag.
+            setLanguage(subtags[0]);
+
+            // The second subtag can either be a script or a region code.
+            // If its size is 4, it's a script code, else it's a region code.
+            bool hasRegion = false;
+            if (subtags[1].size() == 4) {
+                setScript(subtags[1]);
+            } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
+                setRegion(subtags[1]);
+                hasRegion = true;
+            } else {
+                fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n", part.string());
+                return -1;
+            }
+
+            // The third tag can either be a region code (if the second tag was
+            // a script), else a variant code.
+            if (subtags[2].size() > 4) {
+                setVariant(subtags[2]);
+            } else {
+                setRegion(subtags[2]);
+            }
+        } else if (subtags.size() == 4) {
+            setLanguage(subtags[0]);
+            setScript(subtags[1]);
+            setRegion(subtags[2]);
+            setVariant(subtags[3]);
+        } else {
+            fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name: %s\n", part.string());
+            return -1;
+        }
+
+        return ++currentIndex;
+    } else {
+        if ((part.length() == 2 || part.length() == 3) && isAlpha(part)) {
+            setLanguage(part);
+            if (++currentIndex == size) {
+                return size;
+            }
+        } else {
+            return currentIndex;
+        }
+
+        part = parts[currentIndex];
+        if (part.string()[0] == 'r' && part.length() == 3) {
+            setRegion(part.string() + 1);
+            if (++currentIndex == size) {
+                return size;
+            }
+        }
+    }
+
+    return currentIndex;
+}
+
+
+String8 AaptLocaleValue::toDirName() const {
+    String8 dirName("");
+    if (language[0]) {
+        dirName += language;
+    } else {
+        return dirName;
+    }
+
+    if (script[0]) {
+        dirName += "-s";
+        dirName += script;
+    }
+
+    if (region[0]) {
+        dirName += "-r";
+        dirName += region;
+    }
+
+    if (variant[0]) {
+        dirName += "-v";
+        dirName += variant;
+    }
+
+    return dirName;
+}
+
+void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
+    config.unpackLanguage(language);
+    config.unpackRegion(region);
+    if (config.localeScript[0]) {
+        memcpy(script, config.localeScript, sizeof(config.localeScript));
+    }
+
+    if (config.localeVariant[0]) {
+        memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
+    }
+}
+
+void AaptLocaleValue::writeTo(ResTable_config* out) const {
+    out->packLanguage(language);
+    out->packRegion(region);
+
+    if (script[0]) {
+        memcpy(out->localeScript, script, sizeof(out->localeScript));
+    }
+
+    if (variant[0]) {
+        memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
+    }
+}
+
+
+/* static */ bool
+AaptGroupEntry::parseFilterNamePart(const String8& part, int* axis, AxisValue* value)
 {
     ResTable_config config;
+    memset(&config, 0, sizeof(ResTable_config));
 
     // IMSI - MCC
     if (getMccName(part.string(), &config)) {
         *axis = AXIS_MCC;
-        *value = config.mcc;
-        return 0;
+        value->intValue = config.mcc;
+        return true;
     }
 
     // IMSI - MNC
     if (getMncName(part.string(), &config)) {
         *axis = AXIS_MNC;
-        *value = config.mnc;
-        return 0;
+        value->intValue = config.mnc;
+        return true;
     }
 
     // locale - language
-    if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
-        *axis = AXIS_LANGUAGE;
-        *value = part[1] << 8 | part[0];
-        return 0;
-    }
-
-    // locale - language_REGION
-    if (part.length() == 5 && isalpha(part[0]) && isalpha(part[1])
-            && part[2] == '_' && isalpha(part[3]) && isalpha(part[4])) {
-        *axis = AXIS_LANGUAGE;
-        *value = (part[4] << 24) | (part[3] << 16) | (part[1] << 8) | (part[0]);
-        return 0;
+    if (value->localeValue.initFromFilterString(part)) {
+        *axis = AXIS_LOCALE;
+        return true;
     }
 
     // layout direction
     if (getLayoutDirectionName(part.string(), &config)) {
         *axis = AXIS_LAYOUTDIR;
-        *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
-        return 0;
+        value->intValue = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
+        return true;
     }
 
     // smallest screen dp width
     if (getSmallestScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SMALLESTSCREENWIDTHDP;
-        *value = config.smallestScreenWidthDp;
-        return 0;
+        value->intValue = config.smallestScreenWidthDp;
+        return true;
     }
 
     // screen dp width
     if (getScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SCREENWIDTHDP;
-        *value = config.screenWidthDp;
-        return 0;
+        value->intValue = config.screenWidthDp;
+        return true;
     }
 
     // screen dp height
     if (getScreenHeightDpName(part.string(), &config)) {
         *axis = AXIS_SCREENHEIGHTDP;
-        *value = config.screenHeightDp;
-        return 0;
+        value->intValue = config.screenHeightDp;
+        return true;
     }
 
     // screen layout size
     if (getScreenLayoutSizeName(part.string(), &config)) {
         *axis = AXIS_SCREENLAYOUTSIZE;
-        *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
-        return 0;
+        value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
+        return true;
     }
 
     // screen layout long
     if (getScreenLayoutLongName(part.string(), &config)) {
         *axis = AXIS_SCREENLAYOUTLONG;
-        *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
-        return 0;
+        value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+        return true;
     }
 
     // orientation
     if (getOrientationName(part.string(), &config)) {
         *axis = AXIS_ORIENTATION;
-        *value = config.orientation;
-        return 0;
+        value->intValue = config.orientation;
+        return true;
     }
 
     // ui mode type
     if (getUiModeTypeName(part.string(), &config)) {
         *axis = AXIS_UIMODETYPE;
-        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
-        return 0;
+        value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+        return true;
     }
 
     // ui mode night
     if (getUiModeNightName(part.string(), &config)) {
         *axis = AXIS_UIMODENIGHT;
-        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
-        return 0;
+        value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+        return true;
     }
 
     // density
     if (getDensityName(part.string(), &config)) {
         *axis = AXIS_DENSITY;
-        *value = config.density;
-        return 0;
+        value->intValue = config.density;
+        return true;
     }
 
     // touchscreen
     if (getTouchscreenName(part.string(), &config)) {
         *axis = AXIS_TOUCHSCREEN;
-        *value = config.touchscreen;
-        return 0;
+        value->intValue = config.touchscreen;
+        return true;
     }
 
     // keyboard hidden
     if (getKeysHiddenName(part.string(), &config)) {
         *axis = AXIS_KEYSHIDDEN;
-        *value = config.inputFlags;
-        return 0;
+        value->intValue = config.inputFlags;
+        return true;
     }
 
     // keyboard
     if (getKeyboardName(part.string(), &config)) {
         *axis = AXIS_KEYBOARD;
-        *value = config.keyboard;
-        return 0;
+        value->intValue = config.keyboard;
+        return true;
     }
 
     // navigation hidden
     if (getNavHiddenName(part.string(), &config)) {
         *axis = AXIS_NAVHIDDEN;
-        *value = config.inputFlags;
+        value->intValue = config.inputFlags;
         return 0;
     }
 
     // navigation
     if (getNavigationName(part.string(), &config)) {
         *axis = AXIS_NAVIGATION;
-        *value = config.navigation;
-        return 0;
+        value->intValue = config.navigation;
+        return true;
     }
 
     // screen size
     if (getScreenSizeName(part.string(), &config)) {
         *axis = AXIS_SCREENSIZE;
-        *value = config.screenSize;
-        return 0;
+        value->intValue = config.screenSize;
+        return true;
     }
 
     // version
     if (getVersionName(part.string(), &config)) {
         *axis = AXIS_VERSION;
-        *value = config.version;
-        return 0;
+        value->intValue = config.version;
+        return true;
     }
 
-    return 1;
+    return false;
 }
 
-uint32_t
+AxisValue
 AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
 {
+    AxisValue value;
     switch (axis) {
         case AXIS_MCC:
-            return config.mcc;
+            value.intValue = config.mcc;
+            break;
         case AXIS_MNC:
-            return config.mnc;
-        case AXIS_LANGUAGE:
-            return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
-                | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
+            value.intValue = config.mnc;
+            break;
+        case AXIS_LOCALE:
+            value.localeValue.initFromResTable(config);
+            break;
         case AXIS_LAYOUTDIR:
-            return config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
+            value.intValue = config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
+            break;
         case AXIS_SCREENLAYOUTSIZE:
-            return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+            value.intValue = config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+            break;
         case AXIS_ORIENTATION:
-            return config.orientation;
+            value.intValue = config.orientation;
+            break;
         case AXIS_UIMODETYPE:
-            return (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+            value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+            break;
         case AXIS_UIMODENIGHT:
-            return (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+            value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+            break;
         case AXIS_DENSITY:
-            return config.density;
+            value.intValue = config.density;
+            break;
         case AXIS_TOUCHSCREEN:
-            return config.touchscreen;
+            value.intValue = config.touchscreen;
+            break;
         case AXIS_KEYSHIDDEN:
-            return config.inputFlags;
+            value.intValue = config.inputFlags;
+            break;
         case AXIS_KEYBOARD:
-            return config.keyboard;
+            value.intValue = config.keyboard;
+            break;
         case AXIS_NAVIGATION:
-            return config.navigation;
+            value.intValue = config.navigation;
+            break;
         case AXIS_SCREENSIZE:
-            return config.screenSize;
+            value.intValue = config.screenSize;
+            break;
         case AXIS_SMALLESTSCREENWIDTHDP:
-            return config.smallestScreenWidthDp;
+            value.intValue = config.smallestScreenWidthDp;
+            break;
         case AXIS_SCREENWIDTHDP:
-            return config.screenWidthDp;
+            value.intValue = config.screenWidthDp;
+            break;
         case AXIS_SCREENHEIGHTDP:
-            return config.screenHeightDp;
+            value.intValue = config.screenHeightDp;
+            break;
         case AXIS_VERSION:
-            return config.version;
+            value.intValue = config.version;
+            break;
     }
-    return 0;
+
+    return value;
 }
 
 bool
@@ -371,24 +672,14 @@
     mParamsChanged = true;
 
     Vector<String8> parts;
+    AaptLocaleValue::splitAndLowerCase(dir, &parts, '-');
 
-    String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
+    String8 mcc, mnc, layoutsize, layoutlong, orient, den;
     String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
     String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
-    const char *p = dir;
-    const char *q;
-    while (NULL != (q = strchr(p, '-'))) {
-        String8 val(p, q-p);
-        val.toLower();
-        parts.add(val);
-        //printf("part: %s\n", parts[parts.size()-1].string());
-        p = q+1;
-    }
-    String8 val(p);
-    val.toLower();
-    parts.add(val);
-    //printf("part: %s\n", parts[parts.size()-1].string());
+    AaptLocaleValue locale;
+    int numLocaleComponents = 0;
 
     const int N = parts.size();
     int index = 0;
@@ -429,38 +720,18 @@
         }
         part = parts[index];
     } else {
-        //printf("not mcc: %s\n", part.string());
+        //printf("not mnc: %s\n", part.string());
     }
 
-    // locale - language
-    if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
-        loc = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not language: %s\n", part.string());
+    index = locale.initFromDirName(parts, index);
+    if (index == -1) {
+        return false;
+    }
+    if (index >= N){
+        goto success;
     }
 
-    // locale - region
-    if (loc.length() > 0
-            && part.length() == 3 && part[0] == 'r' && part[0] && part[1]) {
-        loc += "-";
-        part.toUpper();
-        loc += part.string() + 1;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not region: %s\n", part.string());
-    }
-
+    part = parts[index];
     if (getLayoutDirectionName(part.string())) {
         layoutDir = part;
 
@@ -679,7 +950,7 @@
 success:
     this->mcc = mcc;
     this->mnc = mnc;
-    this->locale = loc;
+    this->locale = locale;
     this->screenLayoutSize = layoutsize;
     this->screenLayoutLong = layoutlong;
     this->smallestScreenWidthDp = smallestwidthdp;
@@ -711,7 +982,7 @@
     s += ",";
     s += this->mnc;
     s += ",";
-    s += this->locale;
+    s += locale.toDirName();
     s += ",";
     s += layoutDirection;
     s += ",";
@@ -765,12 +1036,15 @@
         }
         s += mnc;
     }
-    if (this->locale != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += locale;
+
+    const String8 localeComponent = locale.toDirName();
+    if (localeComponent != "") {
+         if (s.length() > 0) {
+             s += "-";
+         }
+         s += localeComponent;
     }
+
     if (this->layoutDirection != "") {
         if (s.length() > 0) {
             s += "-";
@@ -942,55 +1216,6 @@
     return true;
 }
 
-/*
- * Does this directory name fit the pattern of a locale dir ("en-rUS" or
- * "default")?
- *
- * TODO: Should insist that the first two letters are lower case, and the
- * second two are upper.
- */
-bool AaptGroupEntry::getLocaleName(const char* fileName,
-                                   ResTable_config* out)
-{
-    if (strcmp(fileName, kWildcardName) == 0
-            || strcmp(fileName, kDefaultLocale) == 0) {
-        if (out) {
-            out->language[0] = 0;
-            out->language[1] = 0;
-            out->country[0] = 0;
-            out->country[1] = 0;
-        }
-        return true;
-    }
-
-    if (strlen(fileName) == 2 && isalpha(fileName[0]) && isalpha(fileName[1])) {
-        if (out) {
-            out->language[0] = fileName[0];
-            out->language[1] = fileName[1];
-            out->country[0] = 0;
-            out->country[1] = 0;
-        }
-        return true;
-    }
-
-    if (strlen(fileName) == 5 &&
-        isalpha(fileName[0]) &&
-        isalpha(fileName[1]) &&
-        fileName[2] == '-' &&
-        isalpha(fileName[3]) &&
-        isalpha(fileName[4])) {
-        if (out) {
-            out->language[0] = fileName[0];
-            out->language[1] = fileName[1];
-            out->country[0] = fileName[3];
-            out->country[1] = fileName[4];
-        }
-        return true;
-    }
-
-    return false;
-}
-
 bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
 {
     if (strcmp(name, kWildcardName) == 0) {
@@ -1496,18 +1721,18 @@
     return v;
 }
 
-const ResTable_config& AaptGroupEntry::toParams() const
+const ResTable_config AaptGroupEntry::toParams() const
 {
     if (!mParamsChanged) {
         return mParams;
     }
 
     mParamsChanged = false;
-    ResTable_config& params(mParams);
-    memset(&params, 0, sizeof(params));
+    ResTable_config& params = mParams;
+    memset(&params, 0, sizeof(ResTable_config));
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
-    getLocaleName(locale.string(), &params);
+    locale.writeTo(&params);
     getLayoutDirectionName(layoutDirection.string(), &params);
     getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
     getScreenWidthDpName(screenWidthDp.string(), &params);
@@ -1992,7 +2217,9 @@
 
 AaptAssets::AaptAssets()
     : AaptDir(String8(), String8()),
-      mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
+      mHavePrivateSymbols(false),
+      mChanged(false), mHaveIncludedAssets(false),
+      mRes(NULL)
 {
 }
 
@@ -2502,9 +2729,9 @@
             // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
             // pick xhdpi.
             uint32_t preferredDensity = 0;
-            const SortedVector<uint32_t>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
+            const SortedVector<AxisValue>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
             if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
-                preferredDensity = (*preferredConfigs)[0];
+                preferredDensity = (*preferredConfigs)[0].intValue;
             }
 
             // Now deal with preferred configurations.
@@ -2662,7 +2889,7 @@
 {
     const ResTable& res = getIncludedResources();
     // XXX dirty!
-    return const_cast<ResTable&>(res).add(file->getData(), file->getSize(), NULL);
+    return const_cast<ResTable&>(res).add(file->getData(), file->getSize());
 }
 
 const ResTable& AaptAssets::getIncludedResources() const
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 9cc9007..336d08b 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -13,7 +13,6 @@
 #include <utils/RefBase.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
-#include <utils/String8.h>
 #include <utils/Vector.h>
 #include "ZipFile.h"
 
@@ -34,8 +33,7 @@
     AXIS_NONE = 0,
     AXIS_MCC = 1,
     AXIS_MNC,
-    AXIS_LANGUAGE,
-    AXIS_REGION,
+    AXIS_LOCALE,
     AXIS_SCREENLAYOUTSIZE,
     AXIS_SCREENLAYOUTLONG,
     AXIS_ORIENTATION,
@@ -58,6 +56,73 @@
     AXIS_END = AXIS_VERSION,
 };
 
+struct AaptLocaleValue {
+     char language[4];
+     char region[4];
+     char script[4];
+     char variant[8];
+
+     AaptLocaleValue() {
+         memset(this, 0, sizeof(AaptLocaleValue));
+     }
+
+     // Initialize this AaptLocaleValue from a config string.
+     bool initFromFilterString(const String8& config);
+
+     int initFromDirName(const Vector<String8>& parts, const int startIndex);
+
+     // Initialize this AaptLocaleValue from a ResTable_config.
+     void initFromResTable(const ResTable_config& config);
+
+     void writeTo(ResTable_config* out) const;
+
+     String8 toDirName() const;
+
+     int compare(const AaptLocaleValue& other) const {
+         return memcmp(this, &other, sizeof(AaptLocaleValue));
+     }
+
+     static void splitAndLowerCase(const char* const chars, Vector<String8>* parts,
+             const char separator);
+
+     inline bool operator<(const AaptLocaleValue& o) const { return compare(o) < 0; }
+     inline bool operator<=(const AaptLocaleValue& o) const { return compare(o) <= 0; }
+     inline bool operator==(const AaptLocaleValue& o) const { return compare(o) == 0; }
+     inline bool operator!=(const AaptLocaleValue& o) const { return compare(o) != 0; }
+     inline bool operator>=(const AaptLocaleValue& o) const { return compare(o) >= 0; }
+     inline bool operator>(const AaptLocaleValue& o) const { return compare(o) > 0; }
+private:
+     void setLanguage(const char* language);
+     void setRegion(const char* language);
+     void setScript(const char* script);
+     void setVariant(const char* variant);
+};
+
+struct AxisValue {
+    // Used for all axes except AXIS_LOCALE, which is represented
+    // as a AaptLocaleValue value.
+    int intValue;
+    AaptLocaleValue localeValue;
+
+    AxisValue() : intValue(0) {
+    }
+
+    inline int compare(const AxisValue &other) const  {
+        if (intValue != other.intValue) {
+            return intValue - other.intValue;
+        }
+
+        return localeValue.compare(other.localeValue);
+    }
+
+    inline bool operator<(const AxisValue& o) const { return compare(o) < 0; }
+    inline bool operator<=(const AxisValue& o) const { return compare(o) <= 0; }
+    inline bool operator==(const AxisValue& o) const { return compare(o) == 0; }
+    inline bool operator!=(const AxisValue& o) const { return compare(o) != 0; }
+    inline bool operator>=(const AxisValue& o) const { return compare(o) >= 0; }
+    inline bool operator>(const AxisValue& o) const { return compare(o) > 0; }
+};
+
 /**
  * This structure contains a specific variation of a single file out
  * of all the variations it can have that we can have.
@@ -65,22 +130,38 @@
 struct AaptGroupEntry
 {
 public:
-    AaptGroupEntry() : mParamsChanged(true) { }
-    AaptGroupEntry(const String8& _locale, const String8& _vendor)
-        : locale(_locale), vendor(_vendor), mParamsChanged(true) { }
+    AaptGroupEntry() : mParamsChanged(true) {
+        memset(&mParams, 0, sizeof(ResTable_config));
+    }
 
     bool initFromDirName(const char* dir, String8* resType);
 
-    static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
+    static bool parseFilterNamePart(const String8& part, int* axis, AxisValue* value);
 
-    static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
+    static AxisValue getConfigValueForAxis(const ResTable_config& config, int axis);
 
     static bool configSameExcept(const ResTable_config& config,
             const ResTable_config& otherConfig, int axis);
 
+    int compare(const AaptGroupEntry& o) const;
+
+    const ResTable_config toParams() const;
+
+    inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
+    inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
+    inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
+    inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
+    inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
+    inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
+
+    String8 toString() const;
+    String8 toDirName(const String8& resType) const;
+
+    const String8& getVersionString() const { return version; }
+
+private:
     static bool getMccName(const char* name, ResTable_config* out = NULL);
     static bool getMncName(const char* name, ResTable_config* out = NULL);
-    static bool getLocaleName(const char* name, ResTable_config* out = NULL);
     static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
     static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
     static bool getOrientationName(const char* name, ResTable_config* out = NULL);
@@ -99,26 +180,9 @@
     static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL);
     static bool getVersionName(const char* name, ResTable_config* out = NULL);
 
-    int compare(const AaptGroupEntry& o) const;
-
-    const ResTable_config& toParams() const;
-
-    inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
-    inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
-    inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
-    inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
-    inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
-    inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
-
-    String8 toString() const;
-    String8 toDirName(const String8& resType) const;
-
-    const String8& getVersionString() const { return version; }
-
-private:
     String8 mcc;
     String8 mnc;
-    String8 locale;
+    AaptLocaleValue locale;
     String8 vendor;
     String8 smallestScreenWidthDp;
     String8 screenWidthDp;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 5d4232d..3c27a19 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -517,6 +517,7 @@
     // the API version because key resources like icons will have an implicit
     // version if they are using newer config types like density.
     ResTable_config config;
+    memset(&config, 0, sizeof(ResTable_config));
     config.language[0] = 'e';
     config.language[1] = 'n';
     config.country[0] = 'U';
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 386888b..4d29ff7 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -80,6 +80,7 @@
     ResourceDirIterator(const sp<ResourceTypeSet>& set, const String8& resType)
         : mResType(resType), mSet(set), mSetPos(0), mGroupPos(0)
     {
+        memset(&mParams, 0, sizeof(ResTable_config));
     }
 
     inline const sp<AaptGroup>& getGroup() const { return mGroup; }
@@ -1320,8 +1321,7 @@
         }
 
         // Read resources back in,
-        finalResTable.add(resFile->getData(), resFile->getSize(), NULL);
-
+        finalResTable.add(resFile->getData(), resFile->getSize());
 #if 0
         NOISY(
               printf("Generated resources:\n");
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index 8cfd2a5..e8a2be4 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -28,8 +28,8 @@
             mContainsPseudo = true;
         }
         int axis;
-        uint32_t value;
-        if (AaptGroupEntry::parseNamePart(part, &axis, &value)) {
+        AxisValue value;
+        if (!AaptGroupEntry::parseFilterNamePart(part, &axis, &value)) {
             fprintf(stderr, "Invalid configuration: %s\n", arg);
             fprintf(stderr, "                       ");
             for (int i=0; i<p-arg; i++) {
@@ -44,15 +44,20 @@
 
         ssize_t index = mData.indexOfKey(axis);
         if (index < 0) {
-            mData.add(axis, SortedVector<uint32_t>());
+            mData.add(axis, SortedVector<AxisValue>());
         }
-        SortedVector<uint32_t>& sv = mData.editValueFor(axis);
+        SortedVector<AxisValue>& sv = mData.editValueFor(axis);
         sv.add(value);
-        // if it's a locale with a region, also match an unmodified locale of the
-        // same language
-        if (axis == AXIS_LANGUAGE) {
-            if (value & 0xffff0000) {
-                sv.add(value & 0x0000ffff);
+
+        // If it's a locale with a region, script or variant, we should also match an
+        // unmodified locale of the same language
+        if (axis == AXIS_LOCALE) {
+            if (value.localeValue.region[0] || value.localeValue.script[0] ||
+                value.localeValue.variant[0]) {
+                AxisValue copy;
+                memcpy(copy.localeValue.language, value.localeValue.language,
+                       sizeof(value.localeValue.language));
+                sv.add(copy);
             }
         }
         p = q;
@@ -70,9 +75,9 @@
 }
 
 bool
-ResourceFilter::match(int axis, uint32_t value) const
+ResourceFilter::match(int axis, const AxisValue& value) const
 {
-    if (value == 0) {
+    if (value.intValue == 0 && (value.localeValue.language[0] == 0)) {
         // they didn't specify anything so take everything
         return true;
     }
@@ -81,7 +86,7 @@
         // we didn't request anything on this axis so take everything
         return true;
     }
-    const SortedVector<uint32_t>& sv = mData.valueAt(index);
+    const SortedVector<AxisValue>& sv = mData.valueAt(index);
     return sv.indexOf(value) >= 0;
 }
 
@@ -102,7 +107,7 @@
     return true;
 }
 
-const SortedVector<uint32_t>* ResourceFilter::configsForAxis(int axis) const
+const SortedVector<AxisValue>* ResourceFilter::configsForAxis(int axis) const
 {
     ssize_t index = mData.indexOfKey(axis);
     if (index < 0) {
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index 647b7bb..0d127ba 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -19,14 +19,15 @@
     ResourceFilter() : mData(), mContainsPseudo(false) {}
     status_t parse(const char* arg);
     bool isEmpty() const;
-    bool match(int axis, uint32_t value) const;
     bool match(int axis, const ResTable_config& config) const;
     bool match(const ResTable_config& config) const;
-    const SortedVector<uint32_t>* configsForAxis(int axis) const;
+    const SortedVector<AxisValue>* configsForAxis(int axis) const;
     inline bool containsPseudo() const { return mContainsPseudo; }
 
 private:
-    KeyedVector<int,SortedVector<uint32_t> > mData;
+    bool match(int axis, const AxisValue& value) const;
+
+    KeyedVector<int,SortedVector<AxisValue> > mData;
     bool mContainsPseudo;
 };
 
diff --git a/tools/aapt/ResourceIdCache.h b/tools/aapt/ResourceIdCache.h
index 65f7781..e6bcda2 100644
--- a/tools/aapt/ResourceIdCache.h
+++ b/tools/aapt/ResourceIdCache.h
@@ -7,7 +7,6 @@
 #define RESOURCE_ID_CACHE_H
 
 namespace android {
-class android::String16;
 
 class ResourceIdCache {
 public:
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 6ced8b3..38bf540 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1292,8 +1292,8 @@
                 curIsStyled = true;
             } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
                 // Note the existence and locale of every string we process
-                char rawLocale[16];
-                curParams.getLocale(rawLocale);
+                char rawLocale[RESTABLE_MAX_LOCALE_LEN];
+                curParams.getBcp47Locale(rawLocale);
                 String8 locale(rawLocale);
                 String16 name;
                 String16 translatable;
diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
index 7b444aa..224eac6 100644
--- a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
@@ -36,24 +36,24 @@
 /*package*/ class PropertyValuesHolder_Delegate {
 
     @LayoutlibDelegate
-    /*package*/ static int nGetIntMethod(Class<?> targetClass, String methodName) {
+    /*package*/ static long nGetIntMethod(Class<?> targetClass, String methodName) {
         // return 0 to force PropertyValuesHolder to use Java reflection.
         return 0;
     }
 
     @LayoutlibDelegate
-    /*package*/ static int nGetFloatMethod(Class<?> targetClass, String methodName) {
+    /*package*/ static long nGetFloatMethod(Class<?> targetClass, String methodName) {
         // return 0 to force PropertyValuesHolder to use Java reflection.
         return 0;
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nCallIntMethod(Object target, int methodID, int arg) {
+    /*package*/ static void nCallIntMethod(Object target, long methodID, int arg) {
         // do nothing
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nCallFloatMethod(Object target, int methodID, float arg) {
+    /*package*/ static void nCallFloatMethod(Object target, long methodID, float arg) {
         // do nothing
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index d85c3d1..06673c1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -102,7 +102,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) {
+    /*package*/ static Bitmap nativeDecodeAsset(long asset, Rect padding, Options opts) {
         opts.inBitmap = null;
         return null;
     }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 9d21866..73d274c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -786,7 +786,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPath(long nativeCanvas, int path, long paint) {
+    /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
         final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
         if (pathDelegate == null) {
             return;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 1d66586..ebfe9bc 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -654,7 +654,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_invert(long native_object, int inverse) {
+    /*package*/ static boolean native_invert(long native_object, long inverse) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             return false;