Merge "Fix TinyHashMap to use generic hash_type instead of hash_t"
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_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 2b85fef..db84d000 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -411,7 +411,7 @@
 
     ScopedUtfChars pathname(env, pathnameStr);
     if (pathname.c_str() == NULL) {
-        ALOGV("restorecon(%p) => threw exception", pathname);
+        ALOGV("restorecon(%p) => threw exception", pathnameStr);
         return false;
     }
 
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 67d94f9..c2bab91 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -81,6 +81,65 @@
             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.
@@ -292,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)) {
@@ -327,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) ||
@@ -507,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
@@ -515,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);
     }
 
     /**
@@ -535,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);
     }
 
     /**
@@ -555,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);
     }
 
     /**
@@ -575,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);
     }
 
     /**
@@ -616,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);
     }
 
     /**
@@ -636,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);
     }
 
     /**
@@ -656,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);
     }
 
     /**
@@ -794,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.
@@ -803,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, Element.DataType.SIGNED_32);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -819,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, Element.DataType.SIGNED_16);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -835,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, Element.DataType.SIGNED_8);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -851,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, Element.DataType.FLOAT_32);
-        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));
     }
 
     /**
@@ -868,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);
     }
 
     /**
@@ -884,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);
     }
 
     /**
@@ -900,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);
     }
 
     /**
@@ -916,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.
      *
@@ -955,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, Element.DataType.SIGNED_8);
+        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, Element.DataType.SIGNED_16);
-        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, Element.DataType.SIGNED_32);
-        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, Element.DataType.FLOAT_32);
+    /**
+     * 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);
     }
 
@@ -1002,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);
     }
 
     /**
@@ -1019,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);
     }
 
     /**
@@ -1036,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);
     }
 
     /**
@@ -1053,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);
     }
 
     /**
@@ -1129,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, Element.DataType.SIGNED_8);
+        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, Element.DataType.SIGNED_16);
-    }
-
-    /**
-     * @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, Element.DataType.SIGNED_32);
-    }
-
-    /**
-     * @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, Element.DataType.FLOAT_32);
-    }
-
-
-    /**
-     * @hide
      * Copy a rectangular region from the array into the allocation.
      * The array is assumed to be tightly packed.
      *
@@ -1183,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);
     }
 
     /**
@@ -1256,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
@@ -1264,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, Element.DataType.SIGNED_8);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -1279,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, Element.DataType.SIGNED_16);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -1294,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, Element.DataType.SIGNED_32);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -1309,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, Element.DataType.FLOAT_32);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        copyTo(d, Element.DataType.FLOAT_32, d.length);
     }
 
     /**
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index eee4936..842aa23 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -32,7 +32,7 @@
         mDestroyed = false;
     }
 
-    void setID(int id) {
+    void setID(long id) {
         if (mID != 0) {
             throw new RSRuntimeException("Internal Error, reset of object ID.");
         }
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index cdcaff7..04bc7c6 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -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;
             }
@@ -297,7 +297,7 @@
 
         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/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index 0375d2b..cfd11c0 100644
--- a/rs/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/rs/java/android/renderscript/Long4.java b/rs/java/android/renderscript/Long4.java
index 757b910..1a1ad74 100644
--- a/rs/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/rs/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
index dac9e76..969cc25 100644
--- a/rs/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/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 9c8775a..8618764 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -506,8 +506,8 @@
         rsnAllocationResize1D(mContext, id, dimX);
     }
 
-    native long rsnFileA3DCreateFromAssetStream(long con, int assetStream);
-    synchronized long nFileA3DCreateFromAssetStream(int assetStream) {
+    native long rsnFileA3DCreateFromAssetStream(long con, long assetStream);
+    synchronized long nFileA3DCreateFromAssetStream(long assetStream) {
         validate();
         return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
     }
@@ -531,24 +531,24 @@
         validate();
         rsnFileA3DGetIndexEntries(mContext, fileA3D, numEntries, IDs, names);
     }
-    native int  rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
-    synchronized int nFileA3DGetEntryByIndex(long 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(long 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(long 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(long 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);
     }
@@ -665,9 +665,9 @@
         rsnScriptSetVarObj(mContext, id, slot, val);
     }
 
-    native int  rsnScriptCCreate(long 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);
     }
@@ -714,18 +714,18 @@
         rsnScriptGroupExecute(mContext, group);
     }
 
-    native int  rsnSamplerCreate(long 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(long 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();
@@ -791,8 +791,8 @@
         rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
     }
 
-    native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, int loop, float q);
-    synchronized long nPathCreate(int prim, boolean isStatic, long 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);
     }
diff --git a/rs/java/android/renderscript/Sampler.java b/rs/java/android/renderscript/Sampler.java
index 623055fe..8d0e29e 100644
--- a/rs/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/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index b0a5759..cdb2b08 100644
--- a/rs/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/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 024d0c3..80a5da2 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -220,7 +220,7 @@
 nDeviceCreate(JNIEnv *_env, jobject _this)
 {
     LOG_API("nDeviceCreate");
-    return (jint)rsDeviceCreate();
+    return (jlong)rsDeviceCreate();
 }
 
 static void
@@ -241,17 +241,17 @@
 nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
 {
     LOG_API("nContextCreate");
-    return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
+    return (jlong)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
 }
 
 static jlong
 nContextCreateGL(JNIEnv *_env, jobject _this, jlong 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)
+                 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;
@@ -265,7 +265,7 @@
     sc.samplesQ = samplesQ;
 
     LOG_API("nContextCreateGL");
-    return (jint)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
+    return (jlong)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
 }
 
 static void
@@ -355,7 +355,7 @@
         ALOGV("message receive buffer too small.  %i", receiveLen);
     }
     _env->ReleaseIntArrayElements(data, ptr, 0);
-    return id;
+    return (jint)id;
 }
 
 static jint
@@ -370,7 +370,7 @@
     auxDataPtr[0] = (jint)subID;
     auxDataPtr[1] = (jint)receiveLen;
     _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
-    return id;
+    return (jint)id;
 }
 
 static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
@@ -432,7 +432,7 @@
 
     _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
     _env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
-    return (jint)id;
+    return (jlong)id;
 }
 
 static void
@@ -499,7 +499,7 @@
     int elementCount = _env->GetArrayLength(_typeData);
 
     assert(elementCount == 6);
-    LOG_API("nTypeCreate, con(%p)", (RsContext)con);
+    LOG_API("nTypeGetNativeData, con(%p)", (RsContext)con);
 
     uint32_t typeData[6];
     rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
@@ -515,7 +515,7 @@
 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 (jint) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
+    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
 }
 
 static void
@@ -662,7 +662,7 @@
 
 static void
 nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
-                  jint count, jobject data, int sizeBytes, int dataType)
+                  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)",
@@ -671,8 +671,8 @@
 }
 
 static void
-//    native void rsnAllocationElementData1D(int con, int 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, int sizeBytes)
+//    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);
@@ -683,7 +683,7 @@
 
 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, int sizeBytes, int dataType)
+                  jint w, jint h, jobject data, jint sizeBytes, jint dataType)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
@@ -797,9 +797,8 @@
 static jlong
 nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con, jlong native_asset)
 {
-    ALOGV("______nFileA3D %u", (uint32_t) 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;
@@ -837,13 +836,13 @@
 {
     int32_t numEntries = 0;
     rsaFileA3DGetNumIndexEntries((RsContext)con, &numEntries, (RsFile)fileA3D);
-    return numEntries;
+    return (jint)numEntries;
 }
 
 static void
 nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries)
 {
-    ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
+    ALOGV("______nFileA3D %p", (RsFile) fileA3D);
     RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
 
     rsaFileA3DGetIndexEntries((RsContext)con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
@@ -856,43 +855,43 @@
     free(fileEntries);
 }
 
-static int
+static jlong
 nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index)
 {
-    ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
-    jint id = (jint)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
+    ALOGV("______nFileA3D %p", (RsFile) fileA3D);
+    jlong id = (jlong)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
     return id;
 }
 
 // -----------------------------------
 
-static int
+static jlong
 nFontCreateFromFile(JNIEnv *_env, jobject _this, jlong con,
                     jstring fileName, jfloat fontSize, jint dpi)
 {
     AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
-    jint id = (jint)rsFontCreateFromFile((RsContext)con,
+    jlong id = (jlong)rsFontCreateFromFile((RsContext)con,
                                          fileNameUTF.c_str(), fileNameUTF.length(),
                                          fontSize, dpi);
 
     return id;
 }
 
-static int
+static jlong
 nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con,
-                           jstring name, jfloat fontSize, jint dpi, jint native_asset)
+                           jstring name, jfloat fontSize, jint dpi, jlong native_asset)
 {
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
     AutoJavaStringToUTF8 nameUTF(_env, name);
 
-    jint id = (jint)rsFontCreateFromMemory((RsContext)con,
+    jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
                                            nameUTF.c_str(), nameUTF.length(),
                                            fontSize, dpi,
                                            asset->getBuffer(false), asset->getLength());
     return id;
 }
 
-static int
+static jlong
 nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
                      jfloat fontSize, jint dpi)
 {
@@ -907,7 +906,7 @@
         return 0;
     }
 
-    jint id = (jint)rsFontCreateFromMemory((RsContext)con,
+    jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
                                            str.c_str(), str.length(),
                                            fontSize, dpi,
                                            asset->getBuffer(false), asset->getLength());
@@ -1126,7 +1125,7 @@
 
 // -----------------------------------
 
-static jint
+static jlong
 nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
                jstring resName, jstring cacheDir,
                jbyteArray scriptRef, jint length)
@@ -1135,7 +1134,7 @@
 
     AutoJavaStringToUTF8 resNameUTF(_env, resName);
     AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
-    jint ret = 0;
+    jlong ret = 0;
     jbyte* script_ptr = NULL;
     jint _exception = 0;
     jint remaining;
@@ -1161,7 +1160,7 @@
 
     //rsScriptCSetText((RsContext)con, (const char *)script_ptr, length);
 
-    ret = (jint)rsScriptCCreate((RsContext)con,
+    ret = (jlong)rsScriptCCreate((RsContext)con,
                                 resNameUTF.c_str(), resNameUTF.length(),
                                 cacheDirUTF.c_str(), cacheDirUTF.length(),
                                 (const char *)script_ptr, length);
@@ -1172,7 +1171,7 @@
                 _exception ? JNI_ABORT: 0);
     }
 
-    return ret;
+    return (jlong)ret;
 }
 
 static jlong
@@ -1186,14 +1185,14 @@
 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 (jint)rsScriptKernelIDCreate((RsContext)con, (RsScript)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 (jint)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
+    return (jlong)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
 }
 
 static jlong
@@ -1253,7 +1252,7 @@
 
 // ---------------------------------------------------------------------------
 
-static jint
+static jlong
 nProgramStoreCreate(JNIEnv *_env, jobject _this, jlong con,
                     jboolean colorMaskR, jboolean colorMaskG, jboolean colorMaskB, jboolean colorMaskA,
                     jboolean depthMask, jboolean ditherEnable,
@@ -1261,7 +1260,7 @@
                     jint depthFunc)
 {
     LOG_API("nProgramStoreCreate, con(%p)", (RsContext)con);
-    return (jint)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+    return (jlong)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
                                       depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
                                       (RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
 }
@@ -1346,7 +1345,7 @@
 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 (jint)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
+    return (jlong)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
 }
 
 
@@ -1390,12 +1389,12 @@
 
 // ---------------------------------------------------------------------------
 
-static jint
+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 (jint)rsSamplerCreate((RsContext)con,
+    return (jlong)rsSamplerCreate((RsContext)con,
                                  (RsSamplerValue)magFilter,
                                  (RsSamplerValue)minFilter,
                                  (RsSamplerValue)wrapS,
@@ -1407,7 +1406,7 @@
 // ---------------------------------------------------------------------------
 
 static jlong
-nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jint _loop, jfloat q) {
+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,
@@ -1526,15 +1525,15 @@
 {"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
 
 {"rsnFileA3DCreateFromFile",         "(JLjava/lang/String;)J",                (void*)nFileA3DCreateFromFile },
-{"rsnFileA3DCreateFromAssetStream",  "(JI)J",                                 (void*)nFileA3DCreateFromAssetStream },
+{"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)I",                                (void*)nFileA3DGetEntryByIndex },
+{"rsnFileA3DGetEntryByIndex",        "(JJI)J",                                (void*)nFileA3DGetEntryByIndex },
 
-{"rsnFontCreateFromFile",            "(JLjava/lang/String;FI)I",              (void*)nFontCreateFromFile },
-{"rsnFontCreateFromAssetStream",     "(JLjava/lang/String;FII)I",             (void*)nFontCreateFromAssetStream },
-{"rsnFontCreateFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)I",            (void*)nFontCreateFromAsset },
+{"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 },
@@ -1591,7 +1590,7 @@
 {"rsnScriptSetVarVE",                "(JJI[BJ[I)V",                           (void*)nScriptSetVarVE },
 {"rsnScriptSetVarObj",               "(JJIJ)V",                               (void*)nScriptSetVarObj },
 
-{"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)I",  (void*)nScriptCCreate },
+{"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 },
@@ -1600,7 +1599,7 @@
 {"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
 {"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
 
-{"rsnProgramStoreCreate",            "(JZZZZZZIII)I",                         (void*)nProgramStoreCreate },
+{"rsnProgramStoreCreate",            "(JZZZZZZIII)J",                         (void*)nProgramStoreCreate },
 
 {"rsnProgramBindConstants",          "(JJIJ)V",                               (void*)nProgramBindConstants },
 {"rsnProgramBindTexture",            "(JJIJ)V",                               (void*)nProgramBindTexture },
@@ -1616,9 +1615,9 @@
 {"rsnContextBindProgramVertex",      "(JI)V",                                 (void*)nContextBindProgramVertex },
 {"rsnContextBindProgramRaster",      "(JI)V",                                 (void*)nContextBindProgramRaster },
 
-{"rsnSamplerCreate",                 "(JIIIIIF)I",                            (void*)nSamplerCreate },
+{"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
 
-{"rsnPathCreate",                    "(JIZJIF)J",                             (void*)nPathCreate },
+{"rsnPathCreate",                    "(JIZJJF)J",                             (void*)nPathCreate },
 {"rsnMeshCreate",                    "(J[I[I[I)J",                            (void*)nMeshCreate },
 
 {"rsnMeshGetVertexBufferCount",      "(JJ)I",                                 (void*)nMeshGetVertexBufferCount },
@@ -1648,7 +1647,7 @@
     assert(env != NULL);
 
     if (registerFuncs(env) < 0) {
-        ALOGE("ERROR: MediaPlayer native registration failed\n");
+        ALOGE("ERROR: Renderscript native registration failed\n");
         goto bail;
     }
 
diff --git a/services/java/com/android/server/LightsService.java b/services/java/com/android/server/LightsService.java
index a1d655b..e99a3a4 100644
--- a/services/java/com/android/server/LightsService.java
+++ b/services/java/com/android/server/LightsService.java
@@ -96,6 +96,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/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 7e244b9..7ea1fce 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1301,6 +1301,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();
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);
+        }
+    };
+}