Merge "Frameworks/base: Add removeAll for ArraySet"
diff --git a/preloaded-classes b/preloaded-classes
index dee84f0..c8d8c5d 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1172,6 +1172,7 @@
 android.telecom.InCallService
 android.telephony.PhoneNumberUtils
 android.telephony.Rlog
+android.telephony.SignalStrength
 android.telephony.SubscriptionManager
 android.telephony.TelephonyManager
 android.text.AndroidBidi
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 9fe30ae..a211b70 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -794,12 +794,47 @@
      * @param fp
      */
     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
+        setFromFieldPacker(xoff, 0, 0, component_number, fp);
+    }
+
+    /**
+     * @hide
+     * This is only intended to be used by auto-generated code reflected from
+     * the RenderScript script files.
+     *
+     * @param xoff
+     * @param yoff
+     * @param component_number
+     * @param fp
+     */
+    public void setFromFieldPacker(int xoff, int yoff, int component_number, FieldPacker fp) {
+        setFromFieldPacker(xoff, yoff, 0, component_number, fp);
+    }
+
+    /**
+     * @hide
+     * This is only intended to be used by auto-generated code reflected from
+     * the RenderScript script files.
+     *
+     * @param xoff
+     * @param yoff
+     * @param zoff
+     * @param component_number
+     * @param fp
+     */
+    public void setFromFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) {
         mRS.validate();
         if (component_number >= mType.mElement.mElements.length) {
             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
         }
         if(xoff < 0) {
-            throw new RSIllegalArgumentException("Offset must be >= 0.");
+            throw new RSIllegalArgumentException("Offset x must be >= 0.");
+        }
+        if(yoff < 0) {
+            throw new RSIllegalArgumentException("Offset y must be >= 0.");
+        }
+        if(zoff < 0) {
+            throw new RSIllegalArgumentException("Offset z must be >= 0.");
         }
 
         final byte[] data = fp.getData();
@@ -812,8 +847,8 @@
                                                " does not match component size " + eSize + ".");
         }
 
-        mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
-                                     component_number, data, data_length);
+        mRS.nAllocationElementData(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
+                                   component_number, data, data_length);
     }
 
     private void data1DChecks(int off, int count, int len, int dataSize) {
@@ -1327,6 +1362,74 @@
     }
 
     /**
+     * @hide
+     * Copy subelement from the Allocation into an object array.
+     * This is intended to be used with user defined structs
+     *
+     * @param xoff
+     * @param component_number
+     * @param array
+     */
+    public void copyElementTo(int xoff, int component_number, Object array) {
+        copyElementTo(xoff, 0, 0, component_number, array);
+    }
+
+    /**
+     * @hide
+     * Copy subelement from the Allocation into an object array.
+     * This is intended to be used with user defined structs
+     *
+     * @param xoff
+     * @param yoff
+     * @param component_number
+     * @param array
+     */
+    public void copyElementTo(int xoff, int yoff, int component_number, Object array) {
+        copyElementTo(xoff, yoff, 0, component_number, array);
+    }
+
+    /**
+     * @hide
+     * Copy subelement from the Allocation into an object array.
+     * This is intended to be used with user defined structs
+     *
+     * @param xoff
+     * @param yoff
+     * @param zoff
+     * @param component_number
+     * @param array
+     */
+    public void copyElementTo(int xoff, int yoff, int zoff, int component_number, Object array) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copyElementTo");
+        mRS.validate();
+        if (component_number >= mType.mElement.mElements.length) {
+            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
+        }
+        if(xoff < 0) {
+            throw new RSIllegalArgumentException("Offset x must be >= 0.");
+        }
+        if(yoff < 0) {
+            throw new RSIllegalArgumentException("Offset y must be >= 0.");
+        }
+        if(zoff < 0) {
+            throw new RSIllegalArgumentException("Offset z must be >= 0.");
+        }
+
+        Element.DataType dt = validateObjectIsPrimitiveArray(array, false);
+        int array_size = java.lang.reflect.Array.getLength(array) * dt.mSize;
+        int eSize = mType.mElement.mElements[component_number].getBytesSize();
+        eSize *= mType.mElement.mArraySizes[component_number];
+
+        if (array_size < eSize) {
+            throw new RSIllegalArgumentException("Array Size (bytes)" + array_size +
+                                               " is smaller than component size " + eSize + ".");
+        }
+
+        mRS.nAllocationElementRead(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
+                                   component_number, array, eSize, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+    /**
      * Resize a 1D allocation.  The contents of the allocation are preserved.
      * If new elements are allocated objects are created with null contents and
      * the new region is otherwise undefined.
@@ -1358,6 +1461,282 @@
         updateCacheInfo(mType);
     }
 
+    private void copy1DRangeToUnchecked(int off, int count, Object array,
+                                        Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeToUnchecked");
+        final int dataSize = mType.mElement.getBytesSize() * count;
+        data1DChecks(off, count, arrayLen * dt.mSize, dataSize);
+        mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  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 dest data array
+     */
+    public void copy1DRangeToUnchecked(int off, int count, Object array) {
+        copy1DRangeToUnchecked(off, count, array,
+                               validateObjectIsPrimitiveArray(array, false),
+                               java.lang.reflect.Array.getLength(array));
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  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
+     */
+    public void copy1DRangeToUnchecked(int off, int count, int[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  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
+     */
+    public void copy1DRangeToUnchecked(int off, int count, short[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  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
+     */
+    public void copy1DRangeToUnchecked(int off, int count, byte[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  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
+     */
+    public void copy1DRangeToUnchecked(int off, int count, float[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
+    }
+
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  This method does not
+     * 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.
+     */
+    public void copy1DRangeTo(int off, int count, Object array) {
+        copy1DRangeToUnchecked(off, count, array,
+                               validateObjectIsPrimitiveArray(array, true),
+                               java.lang.reflect.Array.getLength(array));
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  This method does not
+     * and will generate exceptions if the Allocation type is not a 32 bit
+     * integer type.
+     *
+     * @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
+     */
+    public void copy1DRangeTo(int off, int count, int[] d) {
+        validateIsInt32();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  This method does not
+     * and will generate exceptions if the Allocation type is not a 16 bit
+     * integer type.
+     *
+     * @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
+     */
+    public void copy1DRangeTo(int off, int count, short[] d) {
+        validateIsInt16();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  This method does not
+     * and will generate exceptions if the Allocation type is not an 8 bit
+     * integer type.
+     *
+     * @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
+     */
+    public void copy1DRangeTo(int off, int count, byte[] d) {
+        validateIsInt8();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * @hide
+     * Copy part of this Allocation into an array.  This method does not
+     * and will generate exceptions if the Allocation type is not a 32 bit float
+     * type.
+     *
+     * @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.
+     */
+    public void copy1DRangeTo(int off, int count, float[] d) {
+        validateIsFloat32();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
+    }
+
+
+    void copy2DRangeToUnchecked(int xoff, int yoff, int w, int h, Object array,
+                                Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeToUnchecked");
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+                              array, arrayLen * dt.mSize, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     *
+     * @param xoff X offset of the region to copy in this Allocation
+     * @param yoff Y offset of the region to copy in this Allocation
+     * @param w Width of the region to copy
+     * @param h Height of the region to copy
+     * @param array Dest Array to be copied into
+     */
+    public void copy2DRangeTo(int xoff, int yoff, int w, int h, Object array) {
+        copy2DRangeToUnchecked(xoff, yoff, w, h, array,
+                               validateObjectIsPrimitiveArray(array, true),
+                               java.lang.reflect.Array.getLength(array));
+    }
+
+    /**
+     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     *
+     * @param xoff X offset of the region to copy in this Allocation
+     * @param yoff Y offset of the region to copy in this Allocation
+     * @param w Width of the region to copy
+     * @param h Height of the region to copy
+     * @param array Dest Array to be copied into
+     */
+    public void copy2DRangeTo(int xoff, int yoff, int w, int h, byte[] data) {
+        validateIsInt8();
+        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
+                               Element.DataType.SIGNED_8, data.length);
+    }
+
+    /**
+     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     *
+     * @param xoff X offset of the region to copy in this Allocation
+     * @param yoff Y offset of the region to copy in this Allocation
+     * @param w Width of the region to copy
+     * @param h Height of the region to copy
+     * @param array Dest Array to be copied into
+     */
+    public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
+        validateIsInt16();
+        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
+                               Element.DataType.SIGNED_16, data.length);
+    }
+
+    /**
+     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     *
+     * @param xoff X offset of the region to copy in this Allocation
+     * @param yoff Y offset of the region to copy in this Allocation
+     * @param w Width of the region to copy
+     * @param h Height of the region to copy
+     * @param array Dest Array to be copied into
+     */
+    public void copy2DRangeTo(int xoff, int yoff, int w, int h, int[] data) {
+        validateIsInt32();
+        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
+                               Element.DataType.SIGNED_32, data.length);
+    }
+
+    /**
+     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     *
+     * @param xoff X offset of the region to copy in this Allocation
+     * @param yoff Y offset of the region to copy in this Allocation
+     * @param w Width of the region to copy
+     * @param h Height of the region to copy
+     * @param array Dest Array to be copied into
+     */
+    public void copy2DRangeTo(int xoff, int yoff, int w, int h, float[] data) {
+        validateIsFloat32();
+        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
+                               Element.DataType.FLOAT_32, data.length);
+    }
+
+
+    /**
+     * @hide
+     *
+     */
+    private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
+                                        Object array, Element.DataType dt, int arrayLen) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeToUnchecked");
+        mRS.validate();
+        validate3DRange(xoff, yoff, zoff, w, h, d);
+        mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+                              array, arrayLen * dt.mSize, dt);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    /**
+     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     *
+     * @param xoff X offset of the region to copy in this Allocation
+     * @param yoff Y offset of the region to copy in this Allocation
+     * @param zoff Z offset of the region to copy in this Allocation
+     * @param w Width of the region to copy
+     * @param h Height of the region to copy
+     * @param d Depth of the region to copy
+     * @param array Dest Array to be copied into
+     */
+    public void copy3DRangeTo(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
+        copy3DRangeToUnchecked(xoff, yoff, zoff, w, h, d, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
+    }
 
     // creation
 
diff --git a/rs/java/android/renderscript/AllocationAdapter.java b/rs/java/android/renderscript/AllocationAdapter.java
index 9e28f7c..183726f 100644
--- a/rs/java/android/renderscript/AllocationAdapter.java
+++ b/rs/java/android/renderscript/AllocationAdapter.java
@@ -72,17 +72,19 @@
     private void updateOffsets() {
         int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
 
-        if (mSelectedArray.length > 0) {
-            a1 = mSelectedArray[0];
-        }
-        if (mSelectedArray.length > 1) {
-            a2 = mSelectedArray[2];
-        }
-        if (mSelectedArray.length > 2) {
-            a3 = mSelectedArray[2];
-        }
-        if (mSelectedArray.length > 3) {
-            a4 = mSelectedArray[3];
+        if (mSelectedArray != null) {
+            if (mSelectedArray.length > 0) {
+                a1 = mSelectedArray[0];
+            }
+            if (mSelectedArray.length > 1) {
+                a2 = mSelectedArray[2];
+            }
+            if (mSelectedArray.length > 2) {
+                a3 = mSelectedArray[2];
+            }
+            if (mSelectedArray.length > 3) {
+                a4 = mSelectedArray[3];
+            }
         }
         mRS.nAllocationAdapterOffset(getID(mRS), mSelectedX, mSelectedY, mSelectedZ,
                                      mSelectedLOD, mSelectedFace.mID, a1, a2, a3, a4);
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 417bfe2..3b40431 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -491,10 +491,10 @@
         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);
-    synchronized void nAllocationElementData1D(long id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
+    native void rsnAllocationElementData(long con,long id, int xoff, int yoff, int zoff, int mip, int compIdx, byte[] d, int sizeBytes);
+    synchronized void nAllocationElementData(long id, int xoff, int yoff, int zoff, int mip, int compIdx, byte[] d, int sizeBytes) {
         validate();
-        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
+        rsnAllocationElementData(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
     }
 
     native void rsnAllocationData2D(long con,
@@ -571,6 +571,15 @@
         rsnAllocationRead1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID);
     }
 
+    native void rsnAllocationElementRead(long con,long id, int xoff, int yoff, int zoff,
+                                         int mip, int compIdx, Object d, int sizeBytes, int dt);
+    synchronized void nAllocationElementRead(long id, int xoff, int yoff, int zoff,
+                                             int mip, int compIdx, Object d, int sizeBytes,
+                                             Element.DataType dt) {
+        validate();
+        rsnAllocationElementRead(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes, dt.mID);
+    }
+
     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,
@@ -579,6 +588,14 @@
         rsnAllocationRead2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID);
     }
 
+    native void rsnAllocationRead3D(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 nAllocationRead3D(long id, int xoff, int yoff, int zoff, int mip,
+                                        int w, int h, int depth, Object d, int sizeBytes, Element.DataType dt) {
+        validate();
+        rsnAllocationRead3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes, dt.mID);
+    }
+
     native long  rsnAllocationGetType(long con, long id);
     synchronized long nAllocationGetType(long id) {
         validate();
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 2612323..a145166 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1026,23 +1026,25 @@
                    ptr, sizeBytes);
 }
 
-// Copies from the Java array data into the Allocation pointed to by alloc.
 static void
-//    native void rsnAllocationElementData1D(long con, long id, int xoff, int compIdx, byte[] d, int sizeBytes);
-nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod,
-                         jint compIdx, jbyteArray data, jint sizeBytes)
+nAllocationElementData(JNIEnv *_env, jobject _this, jlong con, jlong alloc,
+                       jint xoff, jint yoff, jint zoff,
+                       jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
     if (kLogApi) {
-        ALOGD("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), "
-              "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, offset, compIdx, len,
+        ALOGD("nAllocationElementData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), "
+              "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len,
               sizeBytes);
     }
     jbyte *ptr = _env->GetByteArrayElements(data, nullptr);
-    rsAllocation1DElementData((RsContext)con, (RsAllocation)alloc, offset, lod, ptr, sizeBytes, compIdx);
+    rsAllocationElementData((RsContext)con, (RsAllocation)alloc,
+                            xoff, yoff, zoff,
+                            lod, ptr, sizeBytes, compIdx);
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
 }
 
+
 // Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
@@ -1150,6 +1152,21 @@
     PER_ARRAY_TYPE(0, rsAllocation1DRead, false, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
 }
 
+// Copies from the Element in the Allocation pointed to by _alloc into the Java array data.
+static void
+nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc,
+                       jint xoff, jint yoff, jint zoff,
+                       jint lod, jint compIdx, jobject data, jint sizeBytes, int dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    if (kLogApi) {
+        ALOGD("nAllocationElementRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), "
+              "sizeBytes(%i)", (RsContext)con, alloc, xoff, yoff, zoff, compIdx, sizeBytes);
+    }
+    PER_ARRAY_TYPE(0, rsAllocationElementRead, false, (RsContext)con, alloc,
+                   xoff, yoff, zoff, lod, ptr, sizeBytes, compIdx);
+}
+
 // Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
@@ -1164,6 +1181,20 @@
     PER_ARRAY_TYPE(0, rsAllocation2DRead, false, (RsContext)con, alloc, xoff, yoff, lod, face, w, h,
                    ptr, sizeBytes, 0);
 }
+// Copies from the Allocation pointed to by _alloc into the Java object data.
+static void
+nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
+                  jint w, jint h, jint d, jobject data, int sizeBytes, int dataType)
+{
+    RsAllocation *alloc = (RsAllocation *)_alloc;
+    if (kLogApi) {
+        ALOGD("nAllocation3DRead, 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(0, rsAllocation3DRead, false, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d,
+                   ptr, sizeBytes, 0);
+}
 
 static jlong
 nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
@@ -2184,14 +2215,16 @@
 {"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
 {"rsnAllocationIoReceive",           "(JJ)V",                                 (void*)nAllocationIoReceive },
 {"rsnAllocationData1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationData1D },
-{"rsnAllocationElementData1D",       "(JJIII[BI)V",                           (void*)nAllocationElementData1D },
+{"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
 {"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationData2D },
 {"rsnAllocationData2D",              "(JJIIIIIIJIIII)V",                      (void*)nAllocationData2D_alloc },
 {"rsnAllocationData3D",              "(JJIIIIIIILjava/lang/Object;II)V",      (void*)nAllocationData3D },
 {"rsnAllocationData3D",              "(JJIIIIIIIJIIII)V",                     (void*)nAllocationData3D_alloc },
 {"rsnAllocationRead",                "(JJLjava/lang/Object;I)V",              (void*)nAllocationRead },
 {"rsnAllocationRead1D",              "(JJIIILjava/lang/Object;II)V",          (void*)nAllocationRead1D },
+{"rsnAllocationElementRead",         "(JJIIIIILjava/lang/Object;II)V",        (void*)nAllocationElementRead },
 {"rsnAllocationRead2D",              "(JJIIIIIILjava/lang/Object;II)V",       (void*)nAllocationRead2D },
+{"rsnAllocationRead3D",              "(JJIIIIIIILjava/lang/Object;II)V",      (void*)nAllocationRead3D },
 {"rsnAllocationGetType",             "(JJ)J",                                 (void*)nAllocationGetType},
 {"rsnAllocationResize1D",            "(JJI)V",                                (void*)nAllocationResize1D },
 {"rsnAllocationGenerateMipmaps",     "(JJ)V",                                 (void*)nAllocationGenerateMipmaps },
diff --git a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
index 24318df..04774d4 100644
--- a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
@@ -48,39 +48,6 @@
         super("/data/security/bundle", "sepolicy_bundle", "metadata/", "version");
     }
 
-    private void backupContexts(File contexts) {
-        new File(contexts, versionPath).renameTo(
-                new File(contexts, versionPath + "_backup"));
-
-        new File(contexts, macPermissionsPath).renameTo(
-                new File(contexts, macPermissionsPath + "_backup"));
-
-        new File(contexts, seappContextsPath).renameTo(
-                new File(contexts, seappContextsPath + "_backup"));
-
-        new File(contexts, propertyContextsPath).renameTo(
-                new File(contexts, propertyContextsPath + "_backup"));
-
-        new File(contexts, fileContextsPath).renameTo(
-                new File(contexts, fileContextsPath + "_backup"));
-
-        new File(contexts, sepolicyPath).renameTo(
-                new File(contexts, sepolicyPath + "_backup"));
-
-        new File(contexts, serviceContextsPath).renameTo(
-                new File(contexts, serviceContextsPath + "_backup"));
-    }
-
-    private void copyUpdate(File contexts) {
-        new File(updateDir, versionPath).renameTo(new File(contexts, versionPath));
-        new File(updateDir, macPermissionsPath).renameTo(new File(contexts, macPermissionsPath));
-        new File(updateDir, seappContextsPath).renameTo(new File(contexts, seappContextsPath));
-        new File(updateDir, propertyContextsPath).renameTo(new File(contexts, propertyContextsPath));
-        new File(updateDir, fileContextsPath).renameTo(new File(contexts, fileContextsPath));
-        new File(updateDir, sepolicyPath).renameTo(new File(contexts, sepolicyPath));
-        new File(updateDir, serviceContextsPath).renameTo(new File(contexts, serviceContextsPath));
-    }
-
     private int readInt(BufferedInputStream reader) throws IOException {
         int value = 0;
         for (int i=0; i < 4; i++) {
@@ -108,17 +75,27 @@
         writeUpdate(updateDir, destination, Base64.decode(chunk, Base64.DEFAULT));
     }
 
+    private void deleteRecursive(File fileOrDirectory) {
+        if (fileOrDirectory.isDirectory())
+            for (File child : fileOrDirectory.listFiles())
+                deleteRecursive(child);
+        fileOrDirectory.delete();
+    }
+
     private void unpackBundle() throws IOException {
         BufferedInputStream stream = new BufferedInputStream(new FileInputStream(updateContent));
+        File tmp = new File(updateDir.getParentFile(), "tmp");
         try {
             int[] chunkLengths = readChunkLengths(stream);
-            installFile(new File(updateDir, versionPath), stream, chunkLengths[0]);
-            installFile(new File(updateDir, macPermissionsPath), stream, chunkLengths[1]);
-            installFile(new File(updateDir, seappContextsPath), stream, chunkLengths[2]);
-            installFile(new File(updateDir, propertyContextsPath), stream, chunkLengths[3]);
-            installFile(new File(updateDir, fileContextsPath), stream, chunkLengths[4]);
-            installFile(new File(updateDir, sepolicyPath), stream, chunkLengths[5]);
-            installFile(new File(updateDir, serviceContextsPath), stream, chunkLengths[6]);
+            deleteRecursive(tmp);
+            tmp.mkdirs();
+            installFile(new File(tmp, versionPath), stream, chunkLengths[0]);
+            installFile(new File(tmp, macPermissionsPath), stream, chunkLengths[1]);
+            installFile(new File(tmp, seappContextsPath), stream, chunkLengths[2]);
+            installFile(new File(tmp, propertyContextsPath), stream, chunkLengths[3]);
+            installFile(new File(tmp, fileContextsPath), stream, chunkLengths[4]);
+            installFile(new File(tmp, sepolicyPath), stream, chunkLengths[5]);
+            installFile(new File(tmp, serviceContextsPath), stream, chunkLengths[6]);
         } finally {
             IoUtils.closeQuietly(stream);
         }
@@ -126,22 +103,22 @@
 
     private void applyUpdate() throws IOException, ErrnoException {
         Slog.i(TAG, "Applying SELinux policy");
-        File contexts = new File(updateDir.getParentFile(), "contexts");
+        File backup = new File(updateDir.getParentFile(), "backup");
         File current = new File(updateDir.getParentFile(), "current");
-        File update = new File(updateDir.getParentFile(), "update");
         File tmp = new File(updateDir.getParentFile(), "tmp");
         if (current.exists()) {
-            Os.symlink(updateDir.getPath(), update.getPath());
-            Os.rename(update.getPath(), current.getPath());
-        } else {
-            Os.symlink(updateDir.getPath(), current.getPath());
+            deleteRecursive(backup);
+            Os.rename(current.getPath(), backup.getPath());
         }
-        contexts.mkdirs();
-        backupContexts(contexts);
-        copyUpdate(contexts);
-        Os.symlink(contexts.getPath(), tmp.getPath());
-        Os.rename(tmp.getPath(), current.getPath());
-        SystemProperties.set("selinux.reload_policy", "1");
+        try {
+            Os.rename(tmp.getPath(), current.getPath());
+            SystemProperties.set("selinux.reload_policy", "1");
+        } catch (ErrnoException e) {
+            Slog.e(TAG, "Could not update selinux policy: ", e);
+            if (backup.exists()) {
+                Os.rename(backup.getPath(), current.getPath());
+            }
+        }
     }
 
     @Override