[RenderScript] Code clean up & Update the support lib based on native
rs. (java interface)

Change-Id: Ic4807c8913b58e833da57da77a23648feb91ff6b
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java b/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java
index ccc1451..f5a513c 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java
@@ -79,6 +79,65 @@
     int mCurrentDimZ;
     int mCurrentCount;
 
+    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.
@@ -240,9 +299,12 @@
 
         mType = t;
         mUsage = usage;
-        mSize = mType.getCount() * mType.getElement().getBytesSize();
 
         if (t != null) {
+            // TODO: A3D doesn't have Type info during creation, so we can't
+            // calculate the size ahead of time. We can possibly add a method
+            // to update the size in the future if it seems reasonable.
+            mSize = mType.getCount() * mType.getElement().getBytesSize();
             updateCacheInfo(t);
         }
         if (RenderScript.sUseGCHooks == true) {
@@ -306,6 +368,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) ||
@@ -466,6 +536,29 @@
         }
     }
 
+    private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
+        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);
+        }
+    }
+
+    /**
+     * 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
+     */
+    public void copyFromUnchecked(Object array) {
+        copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
+                          java.lang.reflect.Array.getLength(array));
+    }
+
     /**
      * Copy into this Allocation from an array. This method does not guarantee
      * that the Allocation is compatible with the input buffer; it copies memory
@@ -474,15 +567,9 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(int[] d) {
-        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);
-        }
+        copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
     }
+
     /**
      * Copy into this Allocation from an array. This method does not guarantee
      * that the Allocation is compatible with the input buffer; it copies memory
@@ -491,15 +578,9 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(short[] d) {
-        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);
-        }
+        copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
     }
+
     /**
      * Copy into this Allocation from an array. This method does not guarantee
      * that the Allocation is compatible with the input buffer; it copies memory
@@ -508,15 +589,9 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(byte[] d) {
-        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);
-        }
+        copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
     }
+
     /**
      * Copy into this Allocation from an array. This method does not guarantee
      * that the Allocation is compatible with the input buffer; it copies memory
@@ -525,14 +600,21 @@
      * @param d the source data array
      */
     public void copyFromUnchecked(float[] d) {
-        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);
-        }
+        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 array The source data array
+     */
+    public void copyFrom(Object array) {
+        copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
+                          java.lang.reflect.Array.getLength(array));
     }
 
     /**
@@ -543,14 +625,8 @@
      * @param d the source data array
      */
     public void copyFrom(int[] d) {
-        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);
-        }
+        validateIsInt32();
+        copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -561,14 +637,8 @@
      * @param d the source data array
      */
     public void copyFrom(short[] d) {
-        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);
-        }
+        validateIsInt16();
+        copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -579,14 +649,8 @@
      * @param d the source data array
      */
     public void copyFrom(byte[] d) {
-        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);
-        }
+        validateIsInt8();
+        copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -597,14 +661,8 @@
      * @param d the source data array
      */
     public void copyFrom(float[] d) {
-        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);
-        }
+        validateIsFloat32();
+        copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
     }
 
     /**
@@ -732,19 +790,27 @@
         mRS.nAllocationGenerateMipmaps(getID(mRS));
     }
 
+    private void copy1DRangeFromUnchecked(int off, int count, Object array,
+                                          Element.DataType dt, int arrayLen) {
+        final int dataSize = mType.mElement.getBytesSize() * count;
+        data1DChecks(off, count, arrayLen * dt.mSize, dataSize);
+        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt);
+    }
+
     /**
      * 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 d the source data array
+     * @param array The source data array
      */
-    public void copy1DRangeFromUnchecked(int off, int count, long[] d) {
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 8, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
+    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.
@@ -754,10 +820,9 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
     }
+
     /**
      * Copy an array into part of this Allocation.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
@@ -767,10 +832,9 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 2, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
     }
+
     /**
      * Copy an array into part of this Allocation.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
@@ -780,10 +844,9 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
     }
+
     /**
      * Copy an array into part of this Allocation.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
@@ -793,23 +856,23 @@
      * @param d the source data array
      */
     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
-        int dataSize = mType.mElement.getBytesSize() * count;
-        data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
+        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 is not a 32 bit
-     * integer type.
+     * 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 d the source data array
+     * @param array The source data array.
      */
-    public void copy1DRangeFrom(int off, int count, long[] d) {
-        validateIsInt64();
-        copy1DRangeFromUnchecked(off, count, d);
+    public void copy1DRangeFrom(int off, int count, Object array) {
+        copy1DRangeFromUnchecked(off, count, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
     }
 
     /**
@@ -823,7 +886,7 @@
      */
     public void copy1DRangeFrom(int off, int count, int[] d) {
         validateIsInt32();
-        copy1DRangeFromUnchecked(off, count, d);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -837,7 +900,7 @@
      */
     public void copy1DRangeFrom(int off, int count, short[] d) {
         validateIsInt16();
-        copy1DRangeFromUnchecked(off, count, d);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -851,7 +914,7 @@
      */
     public void copy1DRangeFrom(int off, int count, byte[] d) {
         validateIsInt8();
-        copy1DRangeFromUnchecked(off, count, d);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -865,7 +928,7 @@
      */
     public void copy1DRangeFrom(int off, int count, float[] d) {
         validateIsFloat32();
-        copy1DRangeFromUnchecked(off, count, d);
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
     }
 
      /**
@@ -901,42 +964,30 @@
         }
     }
 
-    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) {
         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);
     }
 
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 2);
+    /**
+     * 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 array Data to be placed into the Allocation
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
     }
 
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, long[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 8);
-    }
-
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 4);
-    }
-
-    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) {
-        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.
@@ -949,7 +1000,8 @@
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
         validateIsInt8();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_8, data.length);
     }
 
     /**
@@ -964,22 +1016,8 @@
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
         validateIsInt16();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
-    }
-
-    /**
-     * 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
-     */
-    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, long[] data) {
-        validateIsInt64();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_16, data.length);
     }
 
     /**
@@ -994,7 +1032,8 @@
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
         validateIsInt32();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_32, data.length);
     }
 
     /**
@@ -1009,7 +1048,8 @@
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
         validateIsFloat32();
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.FLOAT_32, data.length);
     }
 
     /**
@@ -1078,60 +1118,16 @@
      * @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) {
         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);
     }
 
     /**
      * @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, long[] data) {
-        mRS.validate();
-        validate3DRange(xoff, yoff, zoff, w, h, d);
-        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
-                              w, h, d, data, data.length * 8);
-    }
-
-    /**
-     * @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.
      *
@@ -1143,45 +1139,10 @@
      * @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, long[] data) {
-        validateIsInt64();
-        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) {
+        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
     }
 
     /**
@@ -1223,6 +1184,24 @@
         mRS.nAllocationCopyToBitmap(getID(mRS), b);
     }
 
+    private void copyTo(Object array, Element.DataType dt, int arrayLen) {
+        mRS.validate();
+        mRS.nAllocationRead(getID(mRS), array, dt);
+    }
+
+    /**
+     * 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.
+     */
+    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
@@ -1232,8 +1211,7 @@
      */
     public void copyTo(byte[] d) {
         validateIsInt8();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
+        copyTo(d, Element.DataType.SIGNED_8, d.length);
     }
 
     /**
@@ -1245,21 +1223,7 @@
      */
     public void copyTo(short[] d) {
         validateIsInt16();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
-    }
-
-    /**
-     * Copy from the Allocation into a int array.  The array must be at least as
-     * large as the Allocation.  The allocation must be of an 32 bit integer
-     * {@link android.support.v8.renderscript.Element} type.
-     *
-     * @param d The array to be set from the Allocation.
-     */
-    public void copyTo(long[] d) {
-        validateIsInt64();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
+        copyTo(d, Element.DataType.SIGNED_16, d.length);
     }
 
     /**
@@ -1271,8 +1235,7 @@
      */
     public void copyTo(int[] d) {
         validateIsInt32();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
+        copyTo(d, Element.DataType.SIGNED_32, d.length);
     }
 
     /**
@@ -1284,8 +1247,7 @@
      */
     public void copyTo(float[] d) {
         validateIsFloat32();
-        mRS.validate();
-        mRS.nAllocationRead(getID(mRS), d);
+        copyTo(d, Element.DataType.FLOAT_32, d.length);
     }
 
     // creation
@@ -1480,6 +1442,7 @@
         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
         }
+
         mRS.nAllocationSetSurface(getID(mRS), sur);
     }
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/Byte2.java b/v8/renderscript/java/src/android/support/v8/renderscript/Byte2.java
index ed1eb9a..2371077 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/Byte2.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/Byte2.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2102 The Android Open Source Project
+ * 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.
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/FieldPacker.java b/v8/renderscript/java/src/android/support/v8/renderscript/FieldPacker.java
index ee19875..ccb6d95 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/FieldPacker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/FieldPacker.java
@@ -36,6 +36,18 @@
         mAlignment = new BitSet();
     }
 
+    public FieldPacker(byte[] data) {
+        // Advance mPos to the end of the buffer, since we are copying in the
+        // full data input.
+        mPos = data.length;
+        mLen = data.length;
+        mData = data;
+        mAlignment = new BitSet();
+        // TODO: We should either have an actual FieldPacker copy constructor
+        // or drop support for computing alignment like this. As it stands,
+        // subAlign() can never work correctly for copied FieldPacker objects.
+    }
+
     public void align(int v) {
         if ((v <= 0) || ((v & (v - 1)) != 0)) {
             throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v);
@@ -47,11 +59,29 @@
         }
     }
 
+    public void subalign(int v) {
+        if ((v & (v - 1)) != 0) {
+            throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v);
+        }
+
+        while ((mPos & (v - 1)) != 0) {
+            mPos--;
+        }
+
+        if (mPos > 0) {
+            while (mAlignment.get(mPos - 1) == true) {
+                mPos--;
+                mAlignment.flip(mPos);
+            }
+        }
+
+    }
+
     public void reset() {
         mPos = 0;
     }
     public void reset(int i) {
-        if ((i < 0) || (i >= mLen)) {
+        if ((i < 0) || (i > mLen)) {
             throw new RSIllegalArgumentException("out of range argument: " + i);
         }
         mPos = i;
@@ -69,12 +99,26 @@
         mData[mPos++] = v;
     }
 
+    public byte subI8() {
+        subalign(1);
+        return mData[--mPos];
+    }
+
     public void addI16(short v) {
         align(2);
         mData[mPos++] = (byte)(v & 0xff);
         mData[mPos++] = (byte)(v >> 8);
     }
 
+    public short subI16() {
+        subalign(2);
+        short v = 0;
+        v = (short)((mData[--mPos] & 0xff) << 8);
+        v = (short)(v | (short)(mData[--mPos] & 0xff));
+        return v;
+    }
+
+
     public void addI32(int v) {
         align(4);
         mData[mPos++] = (byte)(v & 0xff);
@@ -83,6 +127,17 @@
         mData[mPos++] = (byte)((v >> 24) & 0xff);
     }
 
+    public int subI32() {
+        subalign(4);
+        int v = 0;
+        v = ((mData[--mPos] & 0xff) << 24);
+        v = v | ((mData[--mPos] & 0xff) << 16);
+        v = v | ((mData[--mPos] & 0xff) << 8);
+        v = v | ((mData[--mPos] & 0xff));
+        return v;
+    }
+
+
     public void addI64(long v) {
         align(8);
         mData[mPos++] = (byte)(v & 0xff);
@@ -95,8 +150,32 @@
         mData[mPos++] = (byte)((v >> 56) & 0xff);
     }
 
+    public long subI64() {
+        subalign(8);
+        long v = 0;
+        byte x = 0;
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 56l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 48l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 40l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 32l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 24l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 16l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff) << 8l);
+        x = ((mData[--mPos]));
+        v = (long)(v | (((long)x) & 0xff));
+        return v;
+    }
+
     public void addU8(short v) {
         if ((v < 0) || (v > 0xff)) {
+            android.util.Log.e("rs", "FieldPacker.addU8( " + v + " )");
             throw new IllegalArgumentException("Saving value out of range for type");
         }
         mData[mPos++] = (byte)v;
@@ -144,10 +223,18 @@
         addI32(Float.floatToRawIntBits(v));
     }
 
+    public float subF32() {
+        return Float.intBitsToFloat(subI32());
+    }
+
     public void addF64(double v) {
         addI64(Double.doubleToRawLongBits(v));
     }
 
+    public double subF64() {
+        return Double.longBitsToDouble(subI64());
+    }
+
     public void addObj(BaseObj obj) {
         if (obj != null) {
             if (RenderScript.sPointerSize == 8) {
@@ -331,40 +418,496 @@
         addU64(v.w);
     }
 
+
+    public Float2 subFloat2() {
+        Float2 v = new Float2();
+        v.y = subF32();
+        v.x = subF32();
+        return v;
+    }
+    public Float3 subFloat3() {
+        Float3 v = new Float3();
+        v.z = subF32();
+        v.y = subF32();
+        v.x = subF32();
+        return v;
+    }
+    public Float4 subFloat4() {
+        Float4 v = new Float4();
+        v.w = subF32();
+        v.z = subF32();
+        v.y = subF32();
+        v.x = subF32();
+        return v;
+    }
+
+    public Double2 subDouble2() {
+        Double2 v = new Double2();
+        v.y = subF64();
+        v.x = subF64();
+        return v;
+    }
+    public Double3 subDouble3() {
+        Double3 v = new Double3();
+        v.z = subF64();
+        v.y = subF64();
+        v.x = subF64();
+        return v;
+    }
+    public Double4 subDouble4() {
+        Double4 v = new Double4();
+        v.w = subF64();
+        v.z = subF64();
+        v.y = subF64();
+        v.x = subF64();
+        return v;
+    }
+
+    public Byte2 subByte2() {
+        Byte2 v = new Byte2();
+        v.y = subI8();
+        v.x = subI8();
+        return v;
+    }
+    public Byte3 subByte3() {
+        Byte3 v = new Byte3();
+        v.z = subI8();
+        v.y = subI8();
+        v.x = subI8();
+        return v;
+    }
+    public Byte4 subByte4() {
+        Byte4 v = new Byte4();
+        v.w = subI8();
+        v.z = subI8();
+        v.y = subI8();
+        v.x = subI8();
+        return v;
+    }
+
+    public Short2 subShort2() {
+        Short2 v = new Short2();
+        v.y = subI16();
+        v.x = subI16();
+        return v;
+    }
+    public Short3 subShort3() {
+        Short3 v = new Short3();
+        v.z = subI16();
+        v.y = subI16();
+        v.x = subI16();
+        return v;
+    }
+    public Short4 subShort4() {
+        Short4 v = new Short4();
+        v.w = subI16();
+        v.z = subI16();
+        v.y = subI16();
+        v.x = subI16();
+        return v;
+    }
+
+    public Int2 subInt2() {
+        Int2 v = new Int2();
+        v.y = subI32();
+        v.x = subI32();
+        return v;
+    }
+    public Int3 subInt3() {
+        Int3 v = new Int3();
+        v.z = subI32();
+        v.y = subI32();
+        v.x = subI32();
+        return v;
+    }
+    public Int4 subInt4() {
+        Int4 v = new Int4();
+        v.w = subI32();
+        v.z = subI32();
+        v.y = subI32();
+        v.x = subI32();
+        return v;
+    }
+
+    public Long2 subLong2() {
+        Long2 v = new Long2();
+        v.y = subI64();
+        v.x = subI64();
+        return v;
+    }
+    public Long3 subLong3() {
+        Long3 v = new Long3();
+        v.z = subI64();
+        v.y = subI64();
+        v.x = subI64();
+        return v;
+    }
+    public Long4 subLong4() {
+        Long4 v = new Long4();
+        v.w = subI64();
+        v.z = subI64();
+        v.y = subI64();
+        v.x = subI64();
+        return v;
+    }
+
+
+
     public void addMatrix(Matrix4f v) {
         for (int i=0; i < v.mMat.length; i++) {
             addF32(v.mMat[i]);
         }
     }
 
+    public Matrix4f subMatrix4f() {
+        Matrix4f v = new Matrix4f();
+        for (int i = v.mMat.length - 1; i >= 0; i--) {
+            v.mMat[i] = subF32();
+        }
+        return v;
+    }
+
     public void addMatrix(Matrix3f v) {
         for (int i=0; i < v.mMat.length; i++) {
             addF32(v.mMat[i]);
         }
     }
 
+    public Matrix3f subMatrix3f() {
+        Matrix3f v = new Matrix3f();
+        for (int i = v.mMat.length - 1; i >= 0; i--) {
+            v.mMat[i] = subF32();
+        }
+        return v;
+    }
+
     public void addMatrix(Matrix2f v) {
         for (int i=0; i < v.mMat.length; i++) {
             addF32(v.mMat[i]);
         }
     }
 
+    public Matrix2f subMatrix2f() {
+        Matrix2f v = new Matrix2f();
+        for (int i = v.mMat.length - 1; i >= 0; i--) {
+            v.mMat[i] = subF32();
+        }
+        return v;
+    }
+
     public void addBoolean(boolean v) {
         addI8((byte)(v ? 1 : 0));
     }
 
+    public boolean subBoolean() {
+        byte v = subI8();
+        if (v == 1) {
+            return true;
+        }
+        return false;
+    }
+
     public final byte[] getData() {
         return mData;
     }
 
+    /**
+     * Get the actual length used for the FieldPacker.
+     *
+     * @hide
+     */
     public int getPos() {
         return mPos;
     }
 
+    private static void addToPack(FieldPacker fp, Object obj) {
+        if (obj instanceof Boolean) {
+            fp.addBoolean(((Boolean)obj).booleanValue());
+            return;
+        }
+
+        if (obj instanceof Byte) {
+            fp.addI8(((Byte)obj).byteValue());
+            return;
+        }
+
+        if (obj instanceof Short) {
+            fp.addI16(((Short)obj).shortValue());
+            return;
+        }
+
+        if (obj instanceof Integer) {
+            fp.addI32(((Integer)obj).intValue());
+            return;
+        }
+
+        if (obj instanceof Long) {
+            fp.addI64(((Long)obj).longValue());
+            return;
+        }
+
+        if (obj instanceof Float) {
+            fp.addF32(((Float)obj).floatValue());
+            return;
+        }
+
+        if (obj instanceof Double) {
+            fp.addF64(((Double)obj).doubleValue());
+            return;
+        }
+
+        if (obj instanceof Byte2) {
+            fp.addI8((Byte2)obj);
+            return;
+        }
+
+        if (obj instanceof Byte3) {
+            fp.addI8((Byte3)obj);
+            return;
+        }
+
+        if (obj instanceof Byte4) {
+            fp.addI8((Byte4)obj);
+            return;
+        }
+
+        if (obj instanceof Short2) {
+            fp.addI16((Short2)obj);
+            return;
+        }
+
+        if (obj instanceof Short3) {
+            fp.addI16((Short3)obj);
+            return;
+        }
+
+        if (obj instanceof Short4) {
+            fp.addI16((Short4)obj);
+            return;
+        }
+
+        if (obj instanceof Int2) {
+            fp.addI32((Int2)obj);
+            return;
+        }
+
+        if (obj instanceof Int3) {
+            fp.addI32((Int3)obj);
+            return;
+        }
+
+        if (obj instanceof Int4) {
+            fp.addI32((Int4)obj);
+            return;
+        }
+
+        if (obj instanceof Long2) {
+            fp.addI64((Long2)obj);
+            return;
+        }
+
+        if (obj instanceof Long3) {
+            fp.addI64((Long3)obj);
+            return;
+        }
+
+        if (obj instanceof Long4) {
+            fp.addI64((Long4)obj);
+            return;
+        }
+
+        if (obj instanceof Float2) {
+            fp.addF32((Float2)obj);
+            return;
+        }
+
+        if (obj instanceof Float3) {
+            fp.addF32((Float3)obj);
+            return;
+        }
+
+        if (obj instanceof Float4) {
+            fp.addF32((Float4)obj);
+            return;
+        }
+
+        if (obj instanceof Double2) {
+            fp.addF64((Double2)obj);
+            return;
+        }
+
+        if (obj instanceof Double3) {
+            fp.addF64((Double3)obj);
+            return;
+        }
+
+        if (obj instanceof Double4) {
+            fp.addF64((Double4)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix2f) {
+            fp.addMatrix((Matrix2f)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix3f) {
+            fp.addMatrix((Matrix3f)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix4f) {
+            fp.addMatrix((Matrix4f)obj);
+            return;
+        }
+
+        if (obj instanceof BaseObj) {
+            fp.addObj((BaseObj)obj);
+            return;
+        }
+    }
+
+    private static int getPackedSize(Object obj) {
+        if (obj instanceof Boolean) {
+            return 1;
+        }
+
+        if (obj instanceof Byte) {
+            return 1;
+        }
+
+        if (obj instanceof Short) {
+            return 2;
+        }
+
+        if (obj instanceof Integer) {
+            return 4;
+        }
+
+        if (obj instanceof Long) {
+            return 8;
+        }
+
+        if (obj instanceof Float) {
+            return 4;
+        }
+
+        if (obj instanceof Double) {
+            return 8;
+        }
+
+        if (obj instanceof Byte2) {
+            return 2;
+        }
+
+        if (obj instanceof Byte3) {
+            return 3;
+        }
+
+        if (obj instanceof Byte4) {
+            return 4;
+        }
+
+        if (obj instanceof Short2) {
+            return 4;
+        }
+
+        if (obj instanceof Short3) {
+            return 6;
+        }
+
+        if (obj instanceof Short4) {
+            return 8;
+        }
+
+        if (obj instanceof Int2) {
+            return 8;
+        }
+
+        if (obj instanceof Int3) {
+            return 12;
+        }
+
+        if (obj instanceof Int4) {
+            return 16;
+        }
+
+        if (obj instanceof Long2) {
+            return 16;
+        }
+
+        if (obj instanceof Long3) {
+            return 24;
+        }
+
+        if (obj instanceof Long4) {
+            return 32;
+        }
+
+        if (obj instanceof Float2) {
+            return 8;
+        }
+
+        if (obj instanceof Float3) {
+            return 12;
+        }
+
+        if (obj instanceof Float4) {
+            return 16;
+        }
+
+        if (obj instanceof Double2) {
+            return 16;
+        }
+
+        if (obj instanceof Double3) {
+            return 24;
+        }
+
+        if (obj instanceof Double4) {
+            return 32;
+        }
+
+        if (obj instanceof Matrix2f) {
+            return 16;
+        }
+
+        if (obj instanceof Matrix3f) {
+            return 36;
+        }
+
+        if (obj instanceof Matrix4f) {
+            return 64;
+        }
+
+        if (obj instanceof BaseObj) {
+            if (RenderScript.sPointerSize == 8) {
+                return 32;
+            } else {
+                return 4;
+            }
+        }
+
+        return 0;
+    }
+
+    static FieldPacker createFieldPack(Object[] args) {
+        int len = 0;
+        for (Object arg : args) {
+            len += getPackedSize(arg);
+        }
+        FieldPacker fp = new FieldPacker(len);
+        for (Object arg : args) {
+            addToPack(fp, arg);
+        }
+        return fp;
+    }
+
     private final byte mData[];
     private int mPos;
     private int mLen;
     private BitSet mAlignment;
+
 }
 
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java b/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java
index af6476b..a379a30 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java
@@ -376,30 +376,11 @@
         rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
     }
 
-    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, long[] d, int sizeBytes);
-    synchronized void nAllocationData1D(long id, int off, int mip, int count, long[] 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(long con, long id, int off, int mip, int count, int[] d, int sizeBytes);
-    synchronized void nAllocationData1D(long id, int off, int mip, int count, int[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
-    }
-    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, short[] d, int sizeBytes);
-    synchronized void nAllocationData1D(long id, int off, int mip, int count, short[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
-    }
-    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, byte[] d, int sizeBytes);
-    synchronized void nAllocationData1D(long id, int off, int mip, int count, byte[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
-    }
-    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, float[] d, int sizeBytes);
-    synchronized void nAllocationData1D(long 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(long con, long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
@@ -428,31 +409,14 @@
                             srcMip, srcFace);
     }
 
-    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
-    synchronized void nAllocationData2D(long 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(long con, long id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes);
-    synchronized void nAllocationData2D(long 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(long con, long id, int xoff, int yoff, int mip, int face, int w, int h, long[] d, int sizeBytes);
-    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face, int w, int h, long[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
-    }
-    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes);
-    synchronized void nAllocationData2D(long 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(long con, long id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes);
-    synchronized void nAllocationData2D(long 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(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();
@@ -477,58 +441,37 @@
                             srcAlloc, srcXoff, srcYoff, srcZoff, srcMip);
     }
 
-    native void rsnAllocationData3D(long con, long id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, byte[] d, int sizeBytes);
-    synchronized void nAllocationData3D(long 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(long con, long id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, short[] d, int sizeBytes);
-    synchronized void nAllocationData3D(long 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(long con, long id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, long[] d, int sizeBytes);
-    synchronized void nAllocationData3D(long id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, long[] d, int sizeBytes) {
-        validate();
-        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes);
-    }
-    native void rsnAllocationData3D(long con, long id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, int[] d, int sizeBytes);
-    synchronized void nAllocationData3D(long 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(long con, long id, int xoff, int yoff, int zoff, int mip, int w, int h, int depth, float[] d, int sizeBytes);
-    synchronized void nAllocationData3D(long 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(long con, long id, byte[] d);
-    synchronized void nAllocationRead(long 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(long con, long id, short[] d);
-    synchronized void nAllocationRead(long 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(long con, long id, long[] d);
-    synchronized void nAllocationRead(long id, long[] d) {
-        validate();
-        rsnAllocationRead(mContext, id, d);
-    }
-    native void rsnAllocationRead(long con, long id, int[] d);
-    synchronized void nAllocationRead(long id, int[] d) {
-        validate();
-        rsnAllocationRead(mContext, id, d);
-    }
-    native void rsnAllocationRead(long con, long id, float[] d);
-    synchronized void nAllocationRead(long id, float[] d) {
-        validate();
-        rsnAllocationRead(mContext, id, d);
-    }
+
     native long  rsnAllocationGetType(long con, long id);
     synchronized long nAllocationGetType(long id) {
         validate();
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic.java
index fd71364..e59cf6d 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic.java
@@ -27,5 +27,8 @@
 public abstract class ScriptIntrinsic extends Script {
     ScriptIntrinsic(long id, RenderScript rs) {
         super(id, rs);
+        if (id == 0) {
+            throw new RSRuntimeException("Loading of ScriptIntrinsic failed.");
+        }
     }
 }
diff --git a/v8/renderscript/jni/android_renderscript_RenderScript.cpp b/v8/renderscript/jni/android_renderscript_RenderScript.cpp
index ac963c2..bd35a5e 100644
--- a/v8/renderscript/jni/android_renderscript_RenderScript.cpp
+++ b/v8/renderscript/jni/android_renderscript_RenderScript.cpp
@@ -33,6 +33,71 @@
 
 #define NELEM(m) (sizeof(m) / sizeof((m)[0]))
 
+template <typename... T>
+void UNUSED(T... t) {}
+#define PER_ARRAY_TYPE(flag, fnc, readonly, ...) {                                      \
+    jint len = 0;                                                                       \
+    void *ptr = nullptr;                                                                \
+    size_t typeBytes = 0;                                                               \
+    jint relFlag = 0;                                                                   \
+    if (readonly) {                                                                     \
+        /* The on-release mode should only be JNI_ABORT for read-only accesses. */      \
+        relFlag = JNI_ABORT;                                                            \
+    }                                                                                   \
+    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, relFlag);     \
+        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, relFlag);  \
+        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, relFlag);         \
+        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, relFlag);     \
+        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, relFlag);           \
+        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, relFlag);        \
+        return;                                                                         \
+    default:                                                                            \
+        break;                                                                          \
+    }                                                                                   \
+    UNUSED(len, ptr, typeBytes, relFlag);                                               \
+}
+
+
 class AutoJavaStringToUTF8 {
 public:
     AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
@@ -613,70 +678,17 @@
     //bitmap.notifyPixelsChanged();
 }
 
-
+// Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
-nAllocationData1D_l(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset,
-                    jint lod, jint count, jlongArray data, int sizeBytes)
+nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
+                  jint count, jobject data, jint sizeBytes, jint dataType)
 {
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)",
-            (RsContext)con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jlong *ptr = _env->GetLongArrayElements(data, NULL);
-    dispatchTab.Allocation1DData((RsContext)con, (RsAllocation)alloc, offset, lod, count,
-                                 ptr, sizeBytes);
-    _env->ReleaseLongArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_i(JNIEnv *_env, jobject _this, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    dispatchTab.Allocation1DData((RsContext)con, (RsAllocation)alloc, offset, lod, count,
-                                 ptr, sizeBytes);
-    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_s(JNIEnv *_env, jobject _this, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    dispatchTab.Allocation1DData((RsContext)con, (RsAllocation)alloc, offset, lod, count,
-                                 ptr, sizeBytes);
-    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_b(JNIEnv *_env, jobject _this, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    dispatchTab.Allocation1DData((RsContext)con, (RsAllocation)alloc, offset, lod, count,
-                                 ptr, sizeBytes);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData1D_f(JNIEnv *_env, jobject _this, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, offset, count, len, sizeBytes);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    dispatchTab.Allocation1DData((RsContext)con, (RsAllocation)alloc, offset, lod, count,
-                                 ptr, sizeBytes);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
+    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(nullptr, dispatchTab.Allocation1DData, true, (RsContext)con, alloc, offset, lod, count,
+                   ptr, sizeBytes);
 }
 
 static void
@@ -693,69 +705,16 @@
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
 }
 
+// Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
-nAllocationData2D_s(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xoff, jint yoff,
-                    jint lod, jint face, jint w, jint h, jshortArray data, int sizeBytes)
+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)
 {
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DData_s, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    dispatchTab.Allocation2DData((RsContext)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, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, xoff, yoff, lod,
-                                 (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_l(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint xoff, jint yoff,
-                    jint lod, jint face, jint w, jint h, jlongArray 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jlong *ptr = _env->GetLongArrayElements(data, NULL);
-    dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, xoff, yoff, lod,
-                                 (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseLongArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData2D_i(JNIEnv *_env, jobject _this, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    dispatchTab.Allocation2DData((RsContext)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, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, w, h, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    dispatchTab.Allocation2DData((RsContext)con, (RsAllocation)alloc, xoff, yoff, lod,
-                                 (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes, 0);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
+    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(nullptr, dispatchTab.Allocation2DData, true, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
 }
 
 static void
@@ -782,73 +741,16 @@
                                       srcMip, srcFace);
 }
 
+// Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
-nAllocationData3D_s(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
-                    jint xoff, jint yoff, jint zoff,
-                    jint lod, jint w, jint h, jint d, jshortArray data, int sizeBytes)
+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)
 {
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation3DData_s, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    dispatchTab.Allocation3DData((RsContext)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, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    dispatchTab.Allocation3DData((RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
-                                 lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData3D_l(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
-                    jint xoff, jint yoff, jint zoff,
-                    jint lod, jint w, jint h, jint d, jlongArray 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jlong *ptr = _env->GetLongArrayElements(data, NULL);
-    dispatchTab.Allocation3DData((RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
-                                 lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseLongArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData3D_i(JNIEnv *_env, jobject _this, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    dispatchTab.Allocation3DData((RsContext)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, jlong con, jlong 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)",
-            (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, w, h, d, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    dispatchTab.Allocation3DData((RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff,
-                                 lod, w, h, d, ptr, sizeBytes, 0);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
+    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(nullptr, dispatchTab.Allocation3DData, true, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
 }
 
 static void
@@ -873,64 +775,37 @@
                                       srcXoff, srcYoff, srcZoff, srcMip);
 }
 
+// Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
-nAllocationRead_l(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jlongArray data)
+nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, int dataType)
 {
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", (RsContext)con,
-            (RsAllocation)alloc, len);
-    jlong *ptr = _env->GetLongArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    dispatchTab.AllocationRead((RsContext)con, (RsAllocation)alloc, ptr, length * sizeof(int));
-    _env->ReleaseLongArrayElements(data, ptr, 0);
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
+    PER_ARRAY_TYPE(0, dispatchTab.AllocationRead, false, (RsContext)con, alloc, ptr, len * typeBytes);
 }
 
+// Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
-nAllocationRead_i(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jintArray data)
+nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
+                  jint count, jobject data, int sizeBytes, int dataType)
 {
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", (RsContext)con,
-            (RsAllocation)alloc, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    dispatchTab.AllocationRead((RsContext)con, (RsAllocation)alloc, ptr, length * sizeof(int));
-    _env->ReleaseIntArrayElements(data, ptr, 0);
+    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, dispatchTab.Allocation1DRead, false, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
 }
 
+// Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
-nAllocationRead_s(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jshortArray data)
+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)
 {
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", (RsContext)con,
-            (RsAllocation)alloc, len);
-    jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    dispatchTab.AllocationRead((RsContext)con, (RsAllocation)alloc, ptr, length * sizeof(short));
-    _env->ReleaseShortArrayElements(data, ptr, 0);
-}
-
-static void
-nAllocationRead_b(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jbyteArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", (RsContext)con,
-            (RsAllocation)alloc, len);
-    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    dispatchTab.AllocationRead((RsContext)con, (RsAllocation)alloc, ptr, length * sizeof(char));
-    _env->ReleaseByteArrayElements(data, ptr, 0);
-}
-
-static void
-nAllocationRead_f(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jfloatArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", (RsContext)con,
-            (RsAllocation)alloc, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    jsize length = _env->GetArrayLength(data);
-    dispatchTab.AllocationRead((RsContext)con, (RsAllocation)alloc, ptr, length * sizeof(float));
-    _env->ReleaseFloatArrayElements(data, ptr, 0);
+    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, dispatchTab.Allocation2DRead, false, (RsContext)con, alloc, xoff, yoff, lod, face, w, h,
+                   ptr, sizeBytes, 0);
 }
 
 static jlong
@@ -1364,28 +1239,15 @@
 {"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
 {"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
 {"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
-{"rsnAllocationData1D",              "(JJIII[JI)V",                           (void*)nAllocationData1D_l },
-{"rsnAllocationData1D",              "(JJIII[II)V",                           (void*)nAllocationData1D_i },
-{"rsnAllocationData1D",              "(JJIII[SI)V",                           (void*)nAllocationData1D_s },
-{"rsnAllocationData1D",              "(JJIII[BI)V",                           (void*)nAllocationData1D_b },
-{"rsnAllocationData1D",              "(JJIII[FI)V",                           (void*)nAllocationData1D_f },
+{"rsnAllocationData1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationData1D },
 {"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
-{"rsnAllocationData2D",              "(JJIIIIII[JI)V",                        (void*)nAllocationData2D_l },
-{"rsnAllocationData2D",              "(JJIIIIII[II)V",                        (void*)nAllocationData2D_i },
-{"rsnAllocationData2D",              "(JJIIIIII[SI)V",                        (void*)nAllocationData2D_s },
-{"rsnAllocationData2D",              "(JJIIIIII[BI)V",                        (void*)nAllocationData2D_b },
-{"rsnAllocationData2D",              "(JJIIIIII[FI)V",                        (void*)nAllocationData2D_f },
+{"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationData2D },
 {"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
-{"rsnAllocationData3D",              "(JJIIIIIII[JI)V",                       (void*)nAllocationData3D_l },
-{"rsnAllocationData3D",              "(JJIIIIIII[II)V",                       (void*)nAllocationData3D_i },
-{"rsnAllocationData3D",              "(JJIIIIIII[SI)V",                       (void*)nAllocationData3D_s },
-{"rsnAllocationData3D",              "(JJIIIIIII[BI)V",                       (void*)nAllocationData3D_b },
-{"rsnAllocationData3D",              "(JJIIIIIII[FI)V",                       (void*)nAllocationData3D_f },
+{"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;II)V",      (void*)nAllocationData3D },
 {"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
-{"rsnAllocationRead",                "(JJ[I)V",                               (void*)nAllocationRead_i },
-{"rsnAllocationRead",                "(JJ[S)V",                               (void*)nAllocationRead_s },
-{"rsnAllocationRead",                "(JJ[B)V",                               (void*)nAllocationRead_b },
-{"rsnAllocationRead",                "(JJ[F)V",                               (void*)nAllocationRead_f },
+{"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 },