Add API 31 sources

Test: None
Change-Id: Ie45894f7a232b2a15e2439b2527ca1813f334cc5
diff --git a/android/renderscript/Allocation.java b/android/renderscript/Allocation.java
new file mode 100644
index 0000000..d420bd4
--- /dev/null
+++ b/android/renderscript/Allocation.java
@@ -0,0 +1,3373 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Trace;
+import android.util.Log;
+import android.view.Surface;
+
+/**
+ * <p> This class provides the primary method through which data is passed to
+ * and from RenderScript kernels.  An Allocation provides the backing store for
+ * a given {@link android.renderscript.Type}.  </p>
+ *
+ * <p>An Allocation also contains a set of usage flags that denote how the
+ * Allocation could be used. For example, an Allocation may have usage flags
+ * specifying that it can be used from a script as well as input to a {@link
+ * android.renderscript.Sampler}. A developer must synchronize across these
+ * different usages using {@link android.renderscript.Allocation#syncAll} in
+ * order to ensure that different users of the Allocation have a consistent view
+ * of memory. For example, in the case where an Allocation is used as the output
+ * of one kernel and as Sampler input in a later kernel, a developer must call
+ * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the
+ * second kernel to ensure correctness.
+ *
+ * <p>An Allocation can be populated with the {@link #copyFrom} routines. For
+ * more complex Element types, the {@link #copyFromUnchecked} methods can be
+ * used to copy from byte arrays or similar constructs.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Allocation extends BaseObj {
+    private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
+
+    Type mType;
+    boolean mOwningType = false;
+    Bitmap mBitmap;
+    int mUsage;
+    Allocation mAdaptedAllocation;
+    int mSize;
+    MipmapControl mMipmapControl;
+
+    long mTimeStamp = -1;
+    boolean mReadAllowed = true;
+    boolean mWriteAllowed = true;
+    boolean mAutoPadding = false;
+    int mSelectedX;
+    int mSelectedY;
+    int mSelectedZ;
+    int mSelectedLOD;
+    int mSelectedArray[];
+    Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
+
+    int mCurrentDimX;
+    int mCurrentDimY;
+    int mCurrentDimZ;
+    int mCurrentCount;
+    static HashMap<Long, Allocation> mAllocationMap =
+            new HashMap<Long, Allocation>();
+    OnBufferAvailableListener mBufferNotifier;
+
+    private Surface mGetSurfaceSurface = null;
+    private ByteBuffer mByteBuffer = null;
+    private long mByteBufferStride = -1;
+
+    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) {
+                validateIsInt16OrFloat16();
+                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;
+        }
+
+        throw new RSIllegalArgumentException("Parameter of type " + cmp.getSimpleName() +
+            "[] is not compatible with data type " + mType.mElement.mType.name() +
+            " of allocation");
+    }
+
+
+    /**
+     * The usage of the Allocation.  These signal to RenderScript where to place
+     * the Allocation in memory.
+     *
+     */
+
+    /**
+     * The Allocation will be bound to and accessed by scripts.
+     */
+    public static final int USAGE_SCRIPT = 0x0001;
+
+    /**
+     * The Allocation will be used as a texture source by one or more graphics
+     * programs.
+     *
+     */
+    public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
+
+    /**
+     * The Allocation will be used as a graphics mesh.
+     *
+     * This was deprecated in API level 16.
+     *
+     */
+    public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
+
+
+    /**
+     * The Allocation will be used as the source of shader constants by one or
+     * more programs.
+     *
+     * This was deprecated in API level 16.
+     *
+     */
+    public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
+
+    /**
+     * The Allocation will be used as a target for offscreen rendering
+     *
+     * This was deprecated in API level 16.
+     *
+     */
+    public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
+
+    /**
+     * The Allocation will be used as a {@link android.view.Surface}
+     * consumer.  This usage will cause the Allocation to be created
+     * as read-only.
+     *
+     */
+    public static final int USAGE_IO_INPUT = 0x0020;
+
+    /**
+     * The Allocation will be used as a {@link android.view.Surface}
+     * producer.  The dimensions and format of the {@link
+     * android.view.Surface} will be forced to those of the
+     * Allocation.
+     *
+     */
+    public static final int USAGE_IO_OUTPUT = 0x0040;
+
+    /**
+     * The Allocation's backing store will be inherited from another object
+     * (usually a {@link android.graphics.Bitmap}); copying to or from the
+     * original source Bitmap will cause a synchronization rather than a full
+     * copy.  {@link #syncAll} may also be used to synchronize the Allocation
+     * and the source Bitmap.
+     *
+     * <p>This is set by default for allocations created with {@link
+     * #createFromBitmap} in API version 18 and higher.</p>
+     *
+     */
+    public static final int USAGE_SHARED = 0x0080;
+
+    /**
+     * Controls mipmap behavior when using the bitmap creation and update
+     * functions.
+     */
+    public enum MipmapControl {
+        /**
+         * No mipmaps will be generated and the type generated from the incoming
+         * bitmap will not contain additional LODs.
+         */
+        MIPMAP_NONE(0),
+
+        /**
+         * A full mipmap chain will be created in script memory.  The Type of
+         * the Allocation will contain a full mipmap chain.  On upload, the full
+         * chain will be transferred.
+         */
+        MIPMAP_FULL(1),
+
+        /**
+         * The Type of the Allocation will be the same as MIPMAP_NONE.  It will
+         * not contain mipmaps.  On upload, the allocation data will contain a
+         * full mipmap chain generated from the top level in script memory.
+         */
+        MIPMAP_ON_SYNC_TO_TEXTURE(2);
+
+        int mID;
+        MipmapControl(int id) {
+            mID = id;
+        }
+    }
+
+
+    private long getIDSafe() {
+        if (mAdaptedAllocation != null) {
+            return mAdaptedAllocation.getID(mRS);
+        }
+        return getID(mRS);
+    }
+
+
+   /**
+     * Get the {@link android.renderscript.Element} of the {@link
+     * android.renderscript.Type} of the Allocation.
+     *
+     * @return Element
+     *
+     */
+    public Element getElement() {
+        return mType.getElement();
+    }
+
+    /**
+     * Get the usage flags of the Allocation.
+     *
+     * @return usage this Allocation's set of the USAGE_* flags OR'd together
+     *
+     */
+    public int getUsage() {
+        return mUsage;
+    }
+
+    /**
+     * @hide
+     * Get the Mipmap control flag of the Allocation.
+     *
+     * @return the Mipmap control flag of the Allocation
+     *
+     */
+    public MipmapControl getMipmap() {
+        return mMipmapControl;
+    }
+
+    /**
+     * Specifies the mapping between the Allocation's cells and an array's elements
+     * when data is copied from the Allocation to the array, or vice-versa.
+     *
+     * Only applies to an Allocation whose Element is a vector of length 3 (such as
+     * {@link Element#U8_3} or {@link Element#RGB_888}). Enabling this feature may make
+     * copying data from the Allocation to an array or vice-versa less efficient.
+     *
+     * <p> Vec3 Element cells are stored in an Allocation as Vec4 Element cells with
+     * the same {@link android.renderscript.Element.DataType}, with the fourth vector
+     * component treated as padding. When this feature is enabled, only the data components,
+     * i.e. the first 3 vector components of each cell, will be mapped between the array
+     * and the Allocation. When disabled, explicit mapping of the padding components
+     * is required, as described in the following example.
+     *
+     * <p> For example, when copying an integer array to an Allocation of two {@link
+     * Element#I32_3} cells using {@link #copyFrom(int[])}:
+     * <p> When disabled:
+     *     The array must have at least 8 integers, with the first 4 integers copied
+     *     to the first cell of the Allocation, and the next 4 integers copied to
+     *     the second cell. The 4th and 8th integers are mapped as the padding components.
+     *
+     * <p> When enabled:
+     *     The array just needs to have at least 6 integers, with the first 3 integers
+     *     copied to the the first cell as data components, and the next 3 copied to
+     *     the second cell. There is no mapping for the padding components.
+     *
+     * <p> Similarly, when copying a byte array to an Allocation of two {@link
+     * Element#I32_3} cells, using {@link #copyFromUnchecked(int[])}:
+     * <p> When disabled:
+     *     The array must have at least 32 bytes, with the first 16 bytes copied
+     *     to the first cell of the Allocation, and the next 16 bytes copied to
+     *     the second cell. The 13th-16th and 29th-32nd bytes are mapped as padding
+     *     components.
+     *
+     * <p> When enabled:
+     *     The array just needs to have at least 24 bytes, with the first 12 bytes copied
+     *     to the first cell of the Allocation, and the next 12 bytes copied to
+     *     the second cell. There is no mapping for the padding components.
+     *
+     * <p> Similar to copying data to an Allocation from an array, when copying data from an
+     * Allocation to an array, the padding components for Vec3 Element cells will not be
+     * copied/mapped to the array if AutoPadding is enabled.
+     *
+     * <p> Default: Disabled.
+     *
+     * @param useAutoPadding True: enable AutoPadding; False: disable AutoPadding
+     *
+     */
+    public void setAutoPadding(boolean useAutoPadding) {
+        mAutoPadding = useAutoPadding;
+    }
+
+    /**
+     * Get the size of the Allocation in bytes.
+     *
+     * @return size of the Allocation in bytes.
+     *
+     */
+    public int getBytesSize() {
+        if (mType.mDimYuv != 0) {
+            return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5);
+        }
+        return mType.getCount() * mType.getElement().getBytesSize();
+    }
+
+    private void updateCacheInfo(Type t) {
+        mCurrentDimX = t.getX();
+        mCurrentDimY = t.getY();
+        mCurrentDimZ = t.getZ();
+        mCurrentCount = mCurrentDimX;
+        if (mCurrentDimY > 1) {
+            mCurrentCount *= mCurrentDimY;
+        }
+        if (mCurrentDimZ > 1) {
+            mCurrentCount *= mCurrentDimZ;
+        }
+    }
+
+    private void setBitmap(Bitmap b) {
+        mBitmap = b;
+    }
+
+    Allocation(long id, RenderScript rs, Type t, int usage) {
+        super(id, rs);
+        if ((usage & ~(USAGE_SCRIPT |
+                       USAGE_GRAPHICS_TEXTURE |
+                       USAGE_GRAPHICS_VERTEX |
+                       USAGE_GRAPHICS_CONSTANTS |
+                       USAGE_GRAPHICS_RENDER_TARGET |
+                       USAGE_IO_INPUT |
+                       USAGE_IO_OUTPUT |
+                       USAGE_SHARED)) != 0) {
+            throw new RSIllegalArgumentException("Unknown usage specified.");
+        }
+
+        if ((usage & USAGE_IO_INPUT) != 0) {
+            mWriteAllowed = false;
+
+            if ((usage & ~(USAGE_IO_INPUT |
+                           USAGE_GRAPHICS_TEXTURE |
+                           USAGE_SCRIPT)) != 0) {
+                throw new RSIllegalArgumentException("Invalid usage combination.");
+            }
+        }
+
+        mType = t;
+        mUsage = usage;
+
+        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);
+        }
+        try {
+            RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize);
+        } catch (Exception e) {
+            Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
+            throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
+        }
+        guard.open("destroy");
+    }
+
+    Allocation(long id, RenderScript rs, Type t, boolean owningType, int usage, MipmapControl mips) {
+        this(id, rs, t, usage);
+        mOwningType = owningType;
+        mMipmapControl = mips;
+    }
+
+    protected void finalize() throws Throwable {
+        RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
+        super.finalize();
+    }
+
+    private void validateIsInt64() {
+        if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
+            (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "64 bit integer source does not match allocation type " + mType.mElement.mType);
+    }
+
+    private void validateIsInt32() {
+        if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
+            (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "32 bit integer source does not match allocation type " + mType.mElement.mType);
+    }
+
+    private void validateIsInt16OrFloat16() {
+        if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
+            (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
+            (mType.mElement.mType == Element.DataType.FLOAT_16)) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "16 bit integer source does not match allocation type " + mType.mElement.mType);
+    }
+
+    private void validateIsInt8() {
+        if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
+            (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "8 bit integer source does not match allocation type " + mType.mElement.mType);
+    }
+
+    private void validateIsFloat32() {
+        if (mType.mElement.mType == Element.DataType.FLOAT_32) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "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) ||
+            (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
+            (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
+            (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
+            (mType.mElement.mType == Element.DataType.RS_MESH) ||
+            (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
+            (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
+            (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
+            (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
+            return;
+        }
+        throw new RSIllegalArgumentException(
+            "Object source does not match allocation type " + mType.mElement.mType);
+    }
+
+    @Override
+    void updateFromNative() {
+        super.updateFromNative();
+        long typeID = mRS.nAllocationGetType(getID(mRS));
+        if(typeID != 0) {
+            mType = new Type(typeID, mRS);
+            mType.updateFromNative();
+            updateCacheInfo(mType);
+        }
+    }
+
+    /**
+     * Get the {@link android.renderscript.Type} of the Allocation.
+     *
+     * @return Type
+     *
+     */
+    public Type getType() {
+        return mType;
+    }
+
+    /**
+     * Propagate changes from one usage of the Allocation to the
+     * other usages of the Allocation.
+     *
+     */
+    public void syncAll(int srcLocation) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
+            switch (srcLocation) {
+                case USAGE_GRAPHICS_TEXTURE:
+                case USAGE_SCRIPT:
+                    if ((mUsage & USAGE_SHARED) != 0) {
+                        copyFrom(mBitmap);
+                    }
+                    break;
+                case USAGE_GRAPHICS_CONSTANTS:
+                case USAGE_GRAPHICS_VERTEX:
+                    break;
+                case USAGE_SHARED:
+                    if ((mUsage & USAGE_SHARED) != 0) {
+                        copyTo(mBitmap);
+                    }
+                    break;
+                default:
+                    throw new RSIllegalArgumentException("Source must be exactly one usage type.");
+            }
+            mRS.validate();
+            mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Send a buffer to the output stream.  The contents of the Allocation will
+     * be undefined after this operation. This operation is only valid if {@link
+     * #USAGE_IO_OUTPUT} is set on the Allocation.
+     *
+     *
+     */
+    public void ioSend() {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
+            if ((mUsage & USAGE_IO_OUTPUT) == 0) {
+                throw new RSIllegalArgumentException(
+                    "Can only send buffer if IO_OUTPUT usage specified.");
+            }
+            mRS.validate();
+            mRS.nAllocationIoSend(getID(mRS));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Receive the latest input into the Allocation. This operation
+     * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
+     *
+     */
+    public void ioReceive() {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
+            if ((mUsage & USAGE_IO_INPUT) == 0) {
+                throw new RSIllegalArgumentException(
+                    "Can only receive if IO_INPUT usage specified.");
+            }
+            mRS.validate();
+            mTimeStamp = mRS.nAllocationIoReceive(getID(mRS));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy an array of RS objects to the Allocation.
+     *
+     * @param d Source array.
+     */
+    public void copyFrom(BaseObj[] d) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            mRS.validate();
+            validateIsObject();
+            if (d.length != mCurrentCount) {
+                throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
+                                                      mCurrentCount + ", array length = " + d.length);
+            }
+
+            if (RenderScript.sPointerSize == 8) {
+                long i[] = new long[d.length * 4];
+                for (int ct=0; ct < d.length; ct++) {
+                    i[ct * 4] = d[ct].getID(mRS);
+                }
+                copy1DRangeFromUnchecked(0, mCurrentCount, i);
+            } else {
+                int i[] = new int[d.length];
+                for (int ct=0; ct < d.length; ct++) {
+                    i[ct] = (int) d[ct].getID(mRS);
+                }
+                copy1DRangeFromUnchecked(0, mCurrentCount, i);
+            }
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    private void validateBitmapFormat(Bitmap b) {
+        Bitmap.Config bc = b.getConfig();
+        if (bc == null) {
+            throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation");
+        }
+        switch (bc) {
+        case ALPHA_8:
+            if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getBytesSize() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+        case ARGB_8888:
+            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
+                (mType.getElement().getBytesSize() != 4)) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getBytesSize() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+        case RGB_565:
+            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
+                (mType.getElement().getBytesSize() != 2)) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getBytesSize() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+        case ARGB_4444:
+            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
+                (mType.getElement().getBytesSize() != 2)) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getBytesSize() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+
+        }
+    }
+
+    private void validateBitmapSize(Bitmap b) {
+        if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
+            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
+        }
+    }
+
+    private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+            mRS.validate();
+            if (mCurrentDimZ > 0) {
+                copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
+            } else if (mCurrentDimY > 0) {
+                copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
+            } else {
+                copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
+            }
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+
+    /**
+     * Copy into this Allocation from an array. This method does not guarantee
+     * that the Allocation is compatible with the input buffer; it copies memory
+     * without reinterpretation.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param array The source array
+     */
+    public void copyFromUnchecked(Object array) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+            copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
+                              java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy into this Allocation from an array. This method does not guarantee
+     * that the Allocation is compatible with the input buffer; it copies memory
+     * without reinterpretation.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFromUnchecked(int[] 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
+     * without reinterpretation.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFromUnchecked(short[] 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
+     * without reinterpretation.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFromUnchecked(byte[] 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
+     * without reinterpretation.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFromUnchecked(float[] 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.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param array The source array
+     */
+    public void copyFrom(Object array) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
+                              java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy into this Allocation from an array.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not a 32 bit integer nor a vector of 32 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFrom(int[] d) {
+        validateIsInt32();
+        copyFromUnchecked(d, Element.DataType.SIGNED_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} is not a 16 bit integer nor a vector of 16 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFrom(short[] d) {
+        validateIsInt16OrFloat16();
+        copyFromUnchecked(d, Element.DataType.SIGNED_16, 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} is not an 8 bit integer nor a vector of 8 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFrom(byte[] d) {
+        validateIsInt8();
+        copyFromUnchecked(d, Element.DataType.SIGNED_8, 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} is neither a 32 bit float nor a vector of
+     * 32 bit floats {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d the source array
+     */
+    public void copyFrom(float[] d) {
+        validateIsFloat32();
+        copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
+    }
+
+    /**
+     * Copy into an Allocation from a {@link android.graphics.Bitmap}.  The
+     * height, width, and format of the bitmap must match the existing
+     * allocation.
+     *
+     * <p>If the {@link android.graphics.Bitmap} is the same as the {@link
+     * android.graphics.Bitmap} used to create the Allocation with {@link
+     * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation,
+     * this will synchronize the Allocation with the latest data from the {@link
+     * android.graphics.Bitmap}, potentially avoiding the actual copy.</p>
+     *
+     * @param b the source bitmap
+     */
+    public void copyFrom(Bitmap b) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            mRS.validate();
+            if (b.getConfig() == null) {
+                Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(newBitmap);
+                c.drawBitmap(b, 0, 0, null);
+                copyFrom(newBitmap);
+                return;
+            }
+            validateBitmapSize(b);
+            validateBitmapFormat(b);
+            mRS.nAllocationCopyFromBitmap(getID(mRS), b);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy an Allocation from an Allocation.  The types of both allocations
+     * must be identical.
+     *
+     * @param a the source allocation
+     */
+    public void copyFrom(Allocation a) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            mRS.validate();
+            if (!mType.equals(a.getType())) {
+                throw new RSIllegalArgumentException("Types of allocations must match.");
+            }
+            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * This is only intended to be used by auto-generated code reflected from
+     * the RenderScript script files and should not be used by developers.
+     *
+     * @param xoff
+     * @param fp
+     */
+    public void setFromFieldPacker(int xoff, FieldPacker fp) {
+        mRS.validate();
+        int eSize = mType.mElement.getBytesSize();
+        final byte[] data = fp.getData();
+        int data_length = fp.getPos();
+
+        int count = data_length / eSize;
+        if ((eSize * count) != data_length) {
+            throw new RSIllegalArgumentException("Field packer length " + data_length +
+                                               " not divisible by element size " + eSize + ".");
+        }
+        copy1DRangeFromUnchecked(xoff, count, data);
+    }
+
+
+    /**
+     * This is only intended to be used by auto-generated code reflected from
+     * the RenderScript script files and should not be used by developers.
+     *
+     * @param xoff
+     * @param component_number
+     * @param fp
+     */
+    public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
+        setFromFieldPacker(xoff, 0, 0, component_number, fp);
+    }
+
+    /**
+     * This is only intended to be used by auto-generated code reflected from
+     * the RenderScript script files and should not be used by developers.
+     *
+     * @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 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();
+        int data_length = fp.getPos();
+        int eSize = mType.mElement.mElements[component_number].getBytesSize();
+        eSize *= mType.mElement.mArraySizes[component_number];
+
+        if (data_length != eSize) {
+            throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
+                                               " does not match component size " + eSize + ".");
+        }
+
+        mRS.nAllocationElementData(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
+                                   component_number, data, data_length);
+    }
+
+    private void data1DChecks(int off, int count, int len, int dataSize, boolean usePadding) {
+        mRS.validate();
+        if(off < 0) {
+            throw new RSIllegalArgumentException("Offset must be >= 0.");
+        }
+        if(count < 1) {
+            throw new RSIllegalArgumentException("Count must be >= 1.");
+        }
+        if((off + count) > mCurrentCount) {
+            throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
+                                               ", got " + count + " at offset " + off + ".");
+        }
+        if(usePadding) {
+            if(len < dataSize / 4 * 3) {
+                throw new RSIllegalArgumentException("Array too small for allocation type.");
+            }
+        } else {
+            if(len < dataSize) {
+                throw new RSIllegalArgumentException("Array too small for allocation type.");
+            }
+        }
+    }
+
+    /**
+     * Generate a mipmap chain. This is only valid if the Type of the Allocation
+     * includes mipmaps.
+     *
+     * <p>This function will generate a complete set of mipmaps from the top
+     * level LOD and place them into the script memory space.</p>
+     *
+     * <p>If the Allocation is also using other memory spaces, a call to {@link
+     * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p>
+     */
+    public void generateMipmaps() {
+        mRS.nAllocationGenerateMipmaps(getID(mRS));
+    }
+
+    private void copy1DRangeFromUnchecked(int off, int count, Object array,
+                                          Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
+            final int dataSize = mType.mElement.getBytesSize() * count;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                usePadding = true;
+            }
+            data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
+            mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param array The source array
+     */
+    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 a 1D region of this Allocation.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
+        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} does not match the component type
+     * of the array passed in.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param array The source array.
+     */
+    public void copy1DRangeFrom(int off, int count, Object array) {
+        copy1DRangeFromUnchecked(off, count, array,
+                                 validateObjectIsPrimitiveArray(array, true),
+                                 java.lang.reflect.Array.getLength(array));
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not an 32 bit integer nor a vector of 32 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFrom(int off, int count, int[] d) {
+        validateIsInt32();
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not an 16 bit integer nor a vector of 16 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFrom(int off, int count, short[] d) {
+        validateIsInt16OrFloat16();
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not an 8 bit integer nor a vector of 8 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeFrom(int off, int count, byte[] d) {
+        validateIsInt8();
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * Copy an array into a 1D region of this Allocation.  This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither a 32 bit float nor a vector of
+     * 32 bit floats {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array.
+     */
+    public void copy1DRangeFrom(int off, int count, float[] d) {
+        validateIsFloat32();
+        copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
+    }
+
+     /**
+     * Copy part of an Allocation into this Allocation.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param data the source data allocation.
+     * @param dataOff off The offset of the first element in data to
+     *          be copied.
+     */
+    public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
+        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
+        mRS.nAllocationData2D(getIDSafe(), off, 0,
+                              mSelectedLOD, mSelectedFace.mID,
+                              count, 1, data.getID(mRS), dataOff, 0,
+                              data.mSelectedLOD, data.mSelectedFace.mID);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
+    }
+
+    private void validate2DRange(int xoff, int yoff, int w, int h) {
+        if (mAdaptedAllocation != null) {
+
+        } else {
+
+            if (xoff < 0 || yoff < 0) {
+                throw new RSIllegalArgumentException("Offset cannot be negative.");
+            }
+            if (h < 0 || w < 0) {
+                throw new RSIllegalArgumentException("Height or width cannot be negative.");
+            }
+            if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
+                throw new RSIllegalArgumentException("Updated region larger than allocation.");
+            }
+        }
+    }
+
+    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
+                                  Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
+            mRS.validate();
+            validate2DRange(xoff, yoff, w, h);
+            final int dataSize = mType.mElement.getBytesSize() * w * h;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+            }
+            mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+                                  array, sizeBytes, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy from an array into a rectangular region in this Allocation.  The
+     * array is assumed to be tightly packed. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} does not match the input data type.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @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) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+            copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
+                                     validateObjectIsPrimitiveArray(array, true),
+                                     java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy from an array into a rectangular region in this Allocation.  The
+     * array is assumed to be tightly packed. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not an 8 bit integer nor a vector of 8 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @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, byte[] data) {
+        validateIsInt8();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_8, data.length);
+    }
+
+    /**
+     * Copy from an array into a rectangular region in this Allocation.  The
+     * array is assumed to be tightly packed. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not a 16 bit integer nor a vector of 16 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @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, short[] data) {
+        validateIsInt16OrFloat16();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_16, data.length);
+    }
+
+    /**
+     * Copy from an array into a rectangular region in this Allocation.  The
+     * array is assumed to be tightly packed. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not a 32 bit integer nor a vector of 32 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @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, int[] data) {
+        validateIsInt32();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.SIGNED_32, data.length);
+    }
+
+    /**
+     * Copy from an array into a rectangular region in this Allocation.  The
+     * array is assumed to be tightly packed. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither a 32 bit float nor a vector of
+     * 32 bit floats {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @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, float[] data) {
+        validateIsFloat32();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+                                 Element.DataType.FLOAT_32, data.length);
+    }
+
+    /**
+     * Copy a rectangular region from an Allocation into a rectangular region in
+     * this Allocation.
+     *
+     * @param xoff X offset of the region in this Allocation
+     * @param yoff Y offset of the region in this Allocation
+     * @param w Width of the region to update.
+     * @param h Height of the region to update.
+     * @param data source Allocation.
+     * @param dataXoff X offset in source Allocation
+     * @param dataYoff Y offset in source Allocation
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
+                                Allocation data, int dataXoff, int dataYoff) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+            mRS.validate();
+            validate2DRange(xoff, yoff, w, h);
+            mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
+                                  mSelectedLOD, mSelectedFace.mID,
+                                  w, h, data.getID(mRS), dataXoff, dataYoff,
+                                  data.mSelectedLOD, data.mSelectedFace.mID);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy a {@link android.graphics.Bitmap} into an Allocation.  The height
+     * and width of the update will use the height and width of the {@link
+     * android.graphics.Bitmap}.
+     *
+     * @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 data the Bitmap to be copied
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+            mRS.validate();
+            if (data.getConfig() == null) {
+                Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(newBitmap);
+                c.drawBitmap(data, 0, 0, null);
+                copy2DRangeFrom(xoff, yoff, newBitmap);
+                return;
+            }
+            validateBitmapFormat(data);
+            validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
+            mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) {
+        if (mAdaptedAllocation != null) {
+
+        } else {
+
+            if (xoff < 0 || yoff < 0 || zoff < 0) {
+                throw new RSIllegalArgumentException("Offset cannot be negative.");
+            }
+            if (h < 0 || w < 0 || d < 0) {
+                throw new RSIllegalArgumentException("Height or width cannot be negative.");
+            }
+            if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
+                throw new RSIllegalArgumentException("Updated region larger than allocation.");
+            }
+        }
+    }
+
+    /**
+     * Copy a rectangular region from the array into the allocation.
+     * The array is assumed to be tightly packed.
+     *
+     * The data type of the array is not required to be the same as
+     * the element data type.
+     */
+    private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
+                                          Object array, Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
+            mRS.validate();
+            validate3DRange(xoff, yoff, zoff, w, h, d);
+            final int dataSize = mType.mElement.getBytesSize() * w * h * d;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+            }
+            mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+                                  array, sizeBytes, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy from an array into a 3D region in this Allocation.  The
+     * array is assumed to be tightly packed. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} does not match the input data type.
+     *
+     * <p> The size of the region is: w * h * d * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @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 zoff Z 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 d Depth of the region to update
+     * @param array to be placed into the allocation
+     */
+    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
+            copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
+                                     validateObjectIsPrimitiveArray(array, true),
+                                     java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy a rectangular region into the allocation from another
+     * allocation.
+     *
+     * @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 zoff Z 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 d Depth of the region to update.
+     * @param data source allocation.
+     * @param dataXoff X offset of the region in the source Allocation
+     * @param dataYoff Y offset of the region in the source Allocation
+     * @param dataZoff Z offset of the region in the source Allocation
+     */
+    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d,
+                                Allocation data, int dataXoff, int dataYoff, int dataZoff) {
+        mRS.validate();
+        validate3DRange(xoff, yoff, zoff, w, h, d);
+        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
+                              w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff,
+                              data.mSelectedLOD);
+    }
+
+
+    /**
+     * Copy from the Allocation into a {@link android.graphics.Bitmap}.  The
+     * bitmap must match the dimensions of the Allocation.
+     *
+     * @param b The bitmap to be set from the Allocation.
+     */
+    public void copyTo(Bitmap b) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+            mRS.validate();
+            validateBitmapFormat(b);
+            validateBitmapSize(b);
+            mRS.nAllocationCopyToBitmap(getID(mRS), b);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    private void copyTo(Object array, Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+            mRS.validate();
+            boolean usePadding = false;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                usePadding = true;
+            }
+            if (usePadding) {
+                if (dt.mSize * arrayLen < mSize / 4 * 3) {
+                    throw new RSIllegalArgumentException(
+                        "Size of output array cannot be smaller than size of allocation.");
+                }
+            } else {
+                if (dt.mSize * arrayLen < mSize) {
+                    throw new RSIllegalArgumentException(
+                        "Size of output array cannot be smaller than size of allocation.");
+                }
+            }
+            mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy from the Allocation into an array. The method is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} does not match the input data type.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells will be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @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. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither an 8 bit integer nor a vector of 8 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells will be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d The array to be set from the Allocation.
+     */
+    public void copyTo(byte[] d) {
+        validateIsInt8();
+        copyTo(d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * Copy from the Allocation into a short array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not a 16 bit integer nor a vector of 16 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells will be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d The array to be set from the Allocation.
+     */
+    public void copyTo(short[] d) {
+        validateIsInt16OrFloat16();
+        copyTo(d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * Copy from the Allocation into a int array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is not a 32 bit integer nor a vector of 32 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells will be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d The array to be set from the Allocation.
+     */
+    public void copyTo(int[] d) {
+        validateIsInt32();
+        copyTo(d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * Copy from the Allocation into a float array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither a 32 bit float nor a vector of
+     * 32 bit floats {@link android.renderscript.Element.DataType}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the Allocation {@link
+     * #getBytesSize getBytesSize()}.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells will be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
+     * the cells must not be part of the array.
+     *
+     * @param d The array to be set from the Allocation.
+     */
+    public void copyTo(float[] d) {
+        validateIsFloat32();
+        copyTo(d, Element.DataType.FLOAT_32, d.length);
+    }
+
+    /**
+     * @hide
+     *
+     * This is only intended to be used by auto-generated code reflected from
+     * the RenderScript script files and should not be used by developers.
+     *
+     * @param xoff
+     * @param yoff
+     * @param zoff
+     * @param component_number
+     * @param fp
+     */
+    public void copyToFieldPacker(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 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();
+        int data_length = data.length;
+        int eSize = mType.mElement.mElements[component_number].getBytesSize();
+        eSize *= mType.mElement.mArraySizes[component_number];
+
+        if (data_length != eSize) {
+            throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
+                                               " does not match component size " + eSize + ".");
+        }
+
+        mRS.nAllocationElementRead(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
+                                   component_number, data, data_length);
+    }
+    /**
+     * 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.
+     *
+     * <p>If the new region is smaller the references of any objects outside the
+     * new region will be released.</p>
+     *
+     * <p>A new type will be created with the new dimension.</p>
+     *
+     * @param dimX The new size of the allocation.
+     *
+     * @deprecated RenderScript objects should be immutable once created.  The
+     * replacement is to create a new allocation and copy the contents. This
+     * function will throw an exception if API 21 or higher is used.
+     */
+    public synchronized void resize(int dimX) {
+        if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) {
+            throw new RSRuntimeException("Resize is not allowed in API 21+.");
+        }
+        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
+            throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
+        }
+        mRS.nAllocationResize1D(getID(mRS), dimX);
+        mRS.finish();  // Necessary because resize is fifoed and update is async.
+
+        long typeID = mRS.nAllocationGetType(getID(mRS));
+        // Sets zero the mID so that the finalizer of the old mType value won't
+        // destroy the native object that is being reused.
+        mType.setID(0);
+        mType = new Type(typeID, mRS);
+        mType.updateFromNative();
+        updateCacheInfo(mType);
+    }
+
+    private void copy1DRangeToUnchecked(int off, int count, Object array,
+                                        Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeToUnchecked");
+            final int dataSize = mType.mElement.getBytesSize() * count;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                usePadding = true;
+            }
+            data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
+            mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param array The dest array
+     */
+    public void copy1DRangeToUnchecked(int off, int count, Object array) {
+        copy1DRangeToUnchecked(off, count, array,
+                               validateObjectIsPrimitiveArray(array, false),
+                               java.lang.reflect.Array.getLength(array));
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeToUnchecked(int off, int count, int[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeToUnchecked(int off, int count, short[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeToUnchecked(int off, int count, byte[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array.  This method does not
+     * guarantee that the Allocation is compatible with the input buffer.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeToUnchecked(int off, int count, float[] d) {
+        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array.  This method is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} does not match the component type
+     * of the array passed in.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param array The source array.
+     */
+    public void copy1DRangeTo(int off, int count, Object array) {
+        copy1DRangeToUnchecked(off, count, array,
+                               validateObjectIsPrimitiveArray(array, true),
+                               java.lang.reflect.Array.getLength(array));
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither a 32 bit integer nor a vector of 32 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeTo(int off, int count, int[] d) {
+        validateIsInt32();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither a 16 bit integer nor a vector of 16 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeTo(int off, int count, short[] d) {
+        validateIsInt16OrFloat16();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither an 8 bit integer nor a vector of 8 bit
+     * integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source array
+     */
+    public void copy1DRangeTo(int off, int count, byte[] d) {
+        validateIsInt8();
+        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
+    }
+
+    /**
+     * Copy a 1D region of this Allocation into an array. This variant is type checked
+     * and will generate exceptions if the Allocation's {@link
+     * android.renderscript.Element} is neither a 32 bit float nor a vector of
+     * 32 bit floats {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: count * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the array.
+     *
+     * @param off The offset of the first element to be copied.
+     * @param count The number of elements to be copied.
+     * @param d the source 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) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeToUnchecked");
+            mRS.validate();
+            validate2DRange(xoff, yoff, w, h);
+            final int dataSize = mType.mElement.getBytesSize() * w * h;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+            }
+            mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+                                  array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Copy from a rectangular region in this Allocation into an array. This
+     * method is type checked and will generate exceptions if the Allocation's
+     * {@link android.renderscript.Element} does not match the component type
+     * of the array passed in.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the 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));
+    }
+
+    /**
+     * Copy from a rectangular region in this Allocation into an array. This
+     * variant is type checked and will generate exceptions if the Allocation's
+     * {@link android.renderscript.Element} is neither an 8 bit integer nor a vector
+     * of 8 bit integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the 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 data 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);
+    }
+
+    /**
+     * Copy from a rectangular region in this Allocation into an array. This
+     * variant is type checked and will generate exceptions if the Allocation's
+     * {@link android.renderscript.Element} is neither a 16 bit integer nor a vector
+     * of 16 bit integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the 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 data Dest Array to be copied into
+     */
+    public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
+        validateIsInt16OrFloat16();
+        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
+                               Element.DataType.SIGNED_16, data.length);
+    }
+
+    /**
+     * Copy from a rectangular region in this Allocation into an array. This
+     * variant is type checked and will generate exceptions if the Allocation's
+     * {@link android.renderscript.Element} is neither a 32 bit integer nor a vector
+     * of 32 bit integers {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the 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 data 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);
+    }
+
+    /**
+     * Copy from a rectangular region in this Allocation into an array. This
+     * variant is type checked and will generate exceptions if the Allocation's
+     * {@link android.renderscript.Element} is neither a 32 bit float nor a vector
+     * of 32 bit floats {@link android.renderscript.Element.DataType}.
+     *
+     * <p> The size of the region is: w * h * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the 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 data 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);
+    }
+
+
+    /**
+     * Copy from a 3D region in this Allocation into an array. This method does
+     * not guarantee that the Allocation is compatible with the input buffer.
+     * The array is assumed to be tightly packed.
+     *
+     * The data type of the array is not required to be the same as
+     * the element data type.
+     */
+    private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
+                                        Object array, Element.DataType dt, int arrayLen) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeToUnchecked");
+            mRS.validate();
+            validate3DRange(xoff, yoff, zoff, w, h, d);
+            final int dataSize = mType.mElement.getBytesSize() * w * h * d;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+            }
+            mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+                                  array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /*
+     * Copy from a 3D region in this Allocation into an array. This
+     * method is type checked and will generate exceptions if the Allocation's
+     * {@link android.renderscript.Element} does not match the component type
+     * of the array passed in.
+     *
+     * <p> The size of the region is: w * h * d * {@link #getElement}.{@link
+     * Element#getBytesSize}.
+     *
+     * <p> If the Allocation does not have Vec3 Elements, then the size of the
+     * array in bytes must be at least the size of the region.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is disabled, then the size of the array in bytes must be at least the size
+     * of the region. The padding bytes for the cells must be part of the array.
+     *
+     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
+     * is enabled, then the size of the array in bytes must be at least 3/4 the size
+     * of the region. The padding bytes for the cells must not be part of the 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
+
+    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+    static {
+        mBitmapOptions.inScaled = false;
+    }
+
+    /**
+     * Creates a new Allocation with the given {@link
+     * android.renderscript.Type}, mipmap flag, and usage flags.
+     *
+     * @param type RenderScript type describing data layout
+     * @param mips specifies desired mipmap behaviour for the
+     *             allocation
+     * @param usage bit field specifying how the Allocation is
+     *              utilized
+     */
+    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
+            rs.validate();
+            if (type.getID(rs) == 0) {
+                throw new RSInvalidStateException("Bad Type");
+            }
+            // TODO: What if there is an exception after this? The native allocation would leak.
+            long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+            if (id == 0) {
+                throw new RSRuntimeException("Allocation creation failed.");
+            }
+            return new Allocation(id, rs, type, false, usage, mips);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Creates an Allocation with the size specified by the type and no mipmaps
+     * generated by default
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param type renderscript type describing data layout
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return allocation
+     */
+    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
+        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
+    }
+
+    /**
+     * Creates an Allocation for use by scripts with a given {@link
+     * android.renderscript.Type} and no mipmaps
+     *
+     * @param rs Context to which the Allocation will belong.
+     * @param type RenderScript Type describing data layout
+     *
+     * @return allocation
+     */
+    static public Allocation createTyped(RenderScript rs, Type type) {
+        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
+    }
+
+    /**
+     * Creates an Allocation with a specified number of given elements
+     *
+     * @param rs Context to which the Allocation will belong.
+     * @param e Element to use in the Allocation
+     * @param count the number of Elements in the Allocation
+     * @param usage bit field specifying how the Allocation is
+     *              utilized
+     *
+     * @return allocation
+     */
+    static public Allocation createSized(RenderScript rs, Element e,
+                                         int count, int usage) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
+            rs.validate();
+            Type.Builder b = new Type.Builder(rs, e);
+            b.setX(count);
+            Type t = b.create();
+
+            long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
+            if (id == 0) {
+                throw new RSRuntimeException("Allocation creation failed.");
+            }
+            return new Allocation(id, rs, t, true, usage, MipmapControl.MIPMAP_NONE);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Creates an Allocation with a specified number of given elements
+     *
+     * @param rs Context to which the Allocation will belong.
+     * @param e Element to use in the Allocation
+     * @param count the number of Elements in the Allocation
+     *
+     * @return allocation
+     */
+    static public Allocation createSized(RenderScript rs, Element e, int count) {
+        return createSized(rs, e, count, USAGE_SCRIPT);
+    }
+
+    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
+        final Bitmap.Config bc = b.getConfig();
+        if (bc == Bitmap.Config.ALPHA_8) {
+            return Element.A_8(rs);
+        }
+        if (bc == Bitmap.Config.ARGB_4444) {
+            return Element.RGBA_4444(rs);
+        }
+        if (bc == Bitmap.Config.ARGB_8888) {
+            return Element.RGBA_8888(rs);
+        }
+        if (bc == Bitmap.Config.RGB_565) {
+            return Element.RGB_565(rs);
+        }
+        throw new RSInvalidStateException("Bad bitmap type: " + bc);
+    }
+
+    static Type typeFromBitmap(RenderScript rs, Bitmap b,
+                                       MipmapControl mip) {
+        Element e = elementFromBitmap(rs, b);
+        Type.Builder tb = new Type.Builder(rs, e);
+        tb.setX(b.getWidth());
+        tb.setY(b.getHeight());
+        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
+        return tb.create();
+    }
+
+    /**
+     * Creates an Allocation from a {@link android.graphics.Bitmap}.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b Bitmap source for the allocation data
+     * @param mips specifies desired mipmap behaviour for the
+     *             allocation
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return Allocation containing bitmap data
+     *
+     */
+    static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
+                                              MipmapControl mips,
+                                              int usage) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
+            rs.validate();
+
+            // WAR undocumented color formats
+            if (b.getConfig() == null) {
+                if ((usage & USAGE_SHARED) != 0) {
+                    throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
+                }
+                Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(newBitmap);
+                c.drawBitmap(b, 0, 0, null);
+                return createFromBitmap(rs, newBitmap, mips, usage);
+            }
+
+            Type t = typeFromBitmap(rs, b, mips);
+
+            // enable optimized bitmap path only with no mipmap and script-only usage
+            if (mips == MipmapControl.MIPMAP_NONE &&
+                 t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
+                 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
+                long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
+                if (id == 0) {
+                    throw new RSRuntimeException("Load failed.");
+                }
+
+                // keep a reference to the Bitmap around to prevent GC
+                Allocation alloc = new Allocation(id, rs, t, true, usage, mips);
+                alloc.setBitmap(b);
+                return alloc;
+            }
+
+
+            long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
+            if (id == 0) {
+                throw new RSRuntimeException("Load failed.");
+            }
+            return new Allocation(id, rs, t, true, usage, mips);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Gets or creates a ByteBuffer that contains the raw data of the current Allocation.
+     * <p> If the Allocation is created with USAGE_IO_INPUT, the returned ByteBuffer
+     * would contain the up-to-date data as READ ONLY.
+     * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
+     * the Allocation has certain alignment. The size of each row including padding,
+     * called stride, can be queried using the {@link #getStride()} method.
+     *
+     * Note: Operating on the ByteBuffer of a destroyed Allocation will triger errors.
+     *
+     * @return ByteBuffer The ByteBuffer associated with raw data pointer of the Allocation.
+     */
+    public ByteBuffer getByteBuffer() {
+        // Create a new ByteBuffer if it is not initialized or using IO_INPUT.
+        if (mType.hasFaces()) {
+            throw new RSInvalidStateException("Cubemap is not supported for getByteBuffer().");
+        }
+        if (mType.getYuv() == android.graphics.ImageFormat.NV21 ||
+            mType.getYuv() == android.graphics.ImageFormat.YV12 ||
+            mType.getYuv() == android.graphics.ImageFormat.YUV_420_888 ) {
+            throw new RSInvalidStateException("YUV format is not supported for getByteBuffer().");
+        }
+        if (mByteBuffer == null || (mUsage & USAGE_IO_INPUT) != 0) {
+            int xBytesSize = mType.getX() * mType.getElement().getBytesSize();
+            long[] stride = new long[1];
+            mByteBuffer = mRS.nAllocationGetByteBuffer(getID(mRS), stride, xBytesSize, mType.getY(), mType.getZ());
+            mByteBufferStride = stride[0];
+        }
+        if ((mUsage & USAGE_IO_INPUT) != 0) {
+            return mByteBuffer.asReadOnlyBuffer();
+        }
+        return mByteBuffer;
+    }
+
+    /**
+     * Creates a new Allocation Array with the given {@link
+     * android.renderscript.Type}, and usage flags.
+     * Note: If the input allocation is of usage: USAGE_IO_INPUT,
+     * the created Allocation will be sharing the same BufferQueue.
+     *
+     * @param rs RenderScript context
+     * @param t RenderScript type describing data layout
+     * @param usage bit field specifying how the Allocation is
+     *              utilized
+     * @param numAlloc Number of Allocations in the array.
+     * @return Allocation[]
+     */
+    public static Allocation[] createAllocations(RenderScript rs, Type t, int usage, int numAlloc) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createAllocations");
+            rs.validate();
+            if (t.getID(rs) == 0) {
+                throw new RSInvalidStateException("Bad Type");
+            }
+
+            Allocation[] mAllocationArray = new Allocation[numAlloc];
+            mAllocationArray[0] = createTyped(rs, t, usage);
+            if ((usage & USAGE_IO_INPUT) != 0) {
+                if (numAlloc > MAX_NUMBER_IO_INPUT_ALLOC) {
+                    mAllocationArray[0].destroy();
+                    throw new RSIllegalArgumentException("Exceeds the max number of Allocations allowed: " +
+                                                         MAX_NUMBER_IO_INPUT_ALLOC);
+                }
+                mAllocationArray[0].setupBufferQueue(numAlloc);;
+            }
+
+            for (int i=1; i<numAlloc; i++) {
+                mAllocationArray[i] = createFromAllocation(rs, mAllocationArray[0]);
+            }
+            return mAllocationArray;
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Creates a new Allocation with the given {@link
+     * android.renderscript.Allocation}. The same data layout of
+     * the input Allocation will be applied.
+     * <p> If the input allocation is of usage: USAGE_IO_INPUT, the created
+     * Allocation will be sharing the same BufferQueue.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param alloc RenderScript Allocation describing data layout.
+     * @return Allocation sharing the same data structure.
+     */
+    static Allocation createFromAllocation(RenderScript rs, Allocation alloc) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
+            rs.validate();
+            if (alloc.getID(rs) == 0) {
+                throw new RSInvalidStateException("Bad input Allocation");
+            }
+
+            Type type = alloc.getType();
+            int usage = alloc.getUsage();
+            MipmapControl mips = alloc.getMipmap();
+            long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+            if (id == 0) {
+                throw new RSRuntimeException("Allocation creation failed.");
+            }
+            Allocation outAlloc = new Allocation(id, rs, type, false, usage, mips);
+            if ((usage & USAGE_IO_INPUT) != 0) {
+                outAlloc.shareBufferQueue(alloc);
+            }
+            return outAlloc;
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Initialize BufferQueue with specified max number of buffers.
+     */
+    void setupBufferQueue(int numAlloc) {
+        mRS.validate();
+        if ((mUsage & USAGE_IO_INPUT) == 0) {
+            throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+        }
+        mRS.nAllocationSetupBufferQueue(getID(mRS), numAlloc);
+    }
+
+    /**
+     * Share the BufferQueue with another {@link #USAGE_IO_INPUT} Allocation.
+     *
+     * @param alloc Allocation to associate with allocation
+     */
+    void shareBufferQueue(Allocation alloc) {
+        mRS.validate();
+        if ((mUsage & USAGE_IO_INPUT) == 0) {
+            throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+        }
+        mGetSurfaceSurface = alloc.getSurface();
+        mRS.nAllocationShareBufferQueue(getID(mRS), alloc.getID(mRS));
+    }
+
+    /**
+     * Gets the stride of the Allocation.
+     * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
+     * the Allocation has certain alignment. The size of each row including such
+     * padding is called stride.
+     *
+     * @return the stride. For 1D Allocation, the stride will be the number of
+     *         bytes of this Allocation. For 2D and 3D Allocations, the stride
+     *         will be the stride in X dimension measuring in bytes.
+     */
+    public long getStride() {
+        if (mByteBufferStride == -1) {
+            getByteBuffer();
+        }
+        return mByteBufferStride;
+    }
+
+    /**
+     * Get the timestamp for the most recent buffer held by this Allocation.
+     * The timestamp is guaranteed to be unique and monotonically increasing.
+     * Default value: -1. The timestamp will be updated after each {@link
+     * #ioReceive ioReceive()} call.
+     *
+     * It can be used to identify the images by comparing the unique timestamps
+     * when used with {@link android.hardware.camera2} APIs.
+     * Example steps:
+     *   1. Save {@link android.hardware.camera2.TotalCaptureResult} when the
+     *      capture is completed.
+     *   2. Get the timestamp after {@link #ioReceive ioReceive()} call.
+     *   3. Comparing totalCaptureResult.get(CaptureResult.SENSOR_TIMESTAMP) with
+     *      alloc.getTimeStamp().
+     * @return long Timestamp associated with the buffer held by the Allocation.
+     */
+    public long getTimeStamp() {
+        return mTimeStamp;
+    }
+
+    /**
+     * Returns the handle to a raw buffer that is being managed by the screen
+     * compositor. This operation is only valid for Allocations with {@link
+     * #USAGE_IO_INPUT}.
+     *
+     * @return Surface object associated with allocation
+     *
+     */
+    public Surface getSurface() {
+        if ((mUsage & USAGE_IO_INPUT) == 0) {
+            throw new RSInvalidStateException("Allocation is not a surface texture.");
+        }
+
+        if (mGetSurfaceSurface == null) {
+            mGetSurfaceSurface = mRS.nAllocationGetSurface(getID(mRS));
+        }
+
+        return mGetSurfaceSurface;
+    }
+
+    /**
+     * Associate a {@link android.view.Surface} with this Allocation. This
+     * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
+     *
+     * @param sur Surface to associate with allocation
+     */
+    public void setSurface(Surface sur) {
+        mRS.validate();
+        if ((mUsage & USAGE_IO_OUTPUT) == 0) {
+            throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
+        }
+
+        mRS.nAllocationSetSurface(getID(mRS), sur);
+    }
+
+    /**
+     * Creates an Allocation from a {@link android.graphics.Bitmap}.
+     *
+     * <p>With target API version 18 or greater, this Allocation will be created
+     * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link
+     * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this
+     * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p>
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b bitmap source for the allocation data
+     *
+     * @return Allocation containing bitmap data
+     *
+     */
+    static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
+        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
+            return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
+                                    USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
+        }
+        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
+                                USAGE_GRAPHICS_TEXTURE);
+    }
+
+    /**
+     * Creates a cubemap Allocation from a {@link android.graphics.Bitmap}
+     * containing the horizontal list of cube faces. Each face must be a square,
+     * have the same size as all other faces, and have a width that is a power
+     * of 2.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b Bitmap with cubemap faces layed out in the following
+     *          format: right, left, top, bottom, front, back
+     * @param mips specifies desired mipmap behaviour for the cubemap
+     * @param usage bit field specifying how the cubemap is utilized
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
+                                                     MipmapControl mips,
+                                                     int usage) {
+        rs.validate();
+
+        int height = b.getHeight();
+        int width = b.getWidth();
+
+        if (width % 6 != 0) {
+            throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
+        }
+        if (width / 6 != height) {
+            throw new RSIllegalArgumentException("Only square cube map faces supported");
+        }
+        boolean isPow2 = (height & (height - 1)) == 0;
+        if (!isPow2) {
+            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
+        }
+
+        Element e = elementFromBitmap(rs, b);
+        Type.Builder tb = new Type.Builder(rs, e);
+        tb.setX(height);
+        tb.setY(height);
+        tb.setFaces(true);
+        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
+        Type t = tb.create();
+
+        long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
+        if(id == 0) {
+            throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
+        }
+        return new Allocation(id, rs, t, true, usage, mips);
+    }
+
+    /**
+     * Creates a non-mipmapped cubemap Allocation for use as a graphics texture
+     * from a {@link android.graphics.Bitmap} containing the horizontal list of
+     * cube faces. Each face must be a square, have the same size as all other
+     * faces, and have a width that is a power of 2.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b bitmap with cubemap faces layed out in the following
+     *          format: right, left, top, bottom, front, back
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromBitmap(RenderScript rs,
+                                                     Bitmap b) {
+        return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
+                                       USAGE_GRAPHICS_TEXTURE);
+    }
+
+    /**
+     * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap}
+     * objects containing the cube faces. Each face must be a square, have the
+     * same size as all other faces, and have a width that is a power of 2.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param xpos cubemap face in the positive x direction
+     * @param xneg cubemap face in the negative x direction
+     * @param ypos cubemap face in the positive y direction
+     * @param yneg cubemap face in the negative y direction
+     * @param zpos cubemap face in the positive z direction
+     * @param zneg cubemap face in the negative z direction
+     * @param mips specifies desired mipmap behaviour for the cubemap
+     * @param usage bit field specifying how the cubemap is utilized
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
+                                                        Bitmap xpos,
+                                                        Bitmap xneg,
+                                                        Bitmap ypos,
+                                                        Bitmap yneg,
+                                                        Bitmap zpos,
+                                                        Bitmap zneg,
+                                                        MipmapControl mips,
+                                                        int usage) {
+        int height = xpos.getHeight();
+        if (xpos.getWidth() != height ||
+            xneg.getWidth() != height || xneg.getHeight() != height ||
+            ypos.getWidth() != height || ypos.getHeight() != height ||
+            yneg.getWidth() != height || yneg.getHeight() != height ||
+            zpos.getWidth() != height || zpos.getHeight() != height ||
+            zneg.getWidth() != height || zneg.getHeight() != height) {
+            throw new RSIllegalArgumentException("Only square cube map faces supported");
+        }
+        boolean isPow2 = (height & (height - 1)) == 0;
+        if (!isPow2) {
+            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
+        }
+
+        Element e = elementFromBitmap(rs, xpos);
+        Type.Builder tb = new Type.Builder(rs, e);
+        tb.setX(height);
+        tb.setY(height);
+        tb.setFaces(true);
+        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
+        Type t = tb.create();
+        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
+
+        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
+        adapter.setFace(Type.CubemapFace.POSITIVE_X);
+        adapter.copyFrom(xpos);
+        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
+        adapter.copyFrom(xneg);
+        adapter.setFace(Type.CubemapFace.POSITIVE_Y);
+        adapter.copyFrom(ypos);
+        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
+        adapter.copyFrom(yneg);
+        adapter.setFace(Type.CubemapFace.POSITIVE_Z);
+        adapter.copyFrom(zpos);
+        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
+        adapter.copyFrom(zneg);
+
+        return cubemap;
+    }
+
+    /**
+     * Creates a non-mipmapped cubemap Allocation for use as a sampler input
+     * from 6 {@link android.graphics.Bitmap} objects containing the cube
+     * faces. Each face must be a square, have the same size as all other faces,
+     * and have a width that is a power of 2.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param xpos cubemap face in the positive x direction
+     * @param xneg cubemap face in the negative x direction
+     * @param ypos cubemap face in the positive y direction
+     * @param yneg cubemap face in the negative y direction
+     * @param zpos cubemap face in the positive z direction
+     * @param zneg cubemap face in the negative z direction
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
+                                                        Bitmap xpos,
+                                                        Bitmap xneg,
+                                                        Bitmap ypos,
+                                                        Bitmap yneg,
+                                                        Bitmap zpos,
+                                                        Bitmap zneg) {
+        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
+                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
+                                          USAGE_GRAPHICS_TEXTURE);
+    }
+
+    /**
+     * Creates an Allocation from the Bitmap referenced
+     * by resource ID.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param res application resources
+     * @param id resource id to load the data from
+     * @param mips specifies desired mipmap behaviour for the
+     *             allocation
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return Allocation containing resource data
+     *
+     */
+    static public Allocation createFromBitmapResource(RenderScript rs,
+                                                      Resources res,
+                                                      int id,
+                                                      MipmapControl mips,
+                                                      int usage) {
+
+        rs.validate();
+        if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
+            throw new RSIllegalArgumentException("Unsupported usage specified.");
+        }
+        Bitmap b = BitmapFactory.decodeResource(res, id);
+        Allocation alloc = createFromBitmap(rs, b, mips, usage);
+        b.recycle();
+        return alloc;
+    }
+
+    /**
+     * Creates a non-mipmapped Allocation to use as a graphics texture from the
+     * {@link android.graphics.Bitmap} referenced by resource ID.
+     *
+     * <p>With target API version 18 or greater, this allocation will be created
+     * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With
+     * target API version 17 or lower, this allocation will be created with
+     * {@link #USAGE_GRAPHICS_TEXTURE}.</p>
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param res application resources
+     * @param id resource id to load the data from
+     *
+     * @return Allocation containing resource data
+     *
+     */
+    static public Allocation createFromBitmapResource(RenderScript rs,
+                                                      Resources res,
+                                                      int id) {
+        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
+            return createFromBitmapResource(rs, res, id,
+                                            MipmapControl.MIPMAP_NONE,
+                                            USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
+        }
+        return createFromBitmapResource(rs, res, id,
+                                        MipmapControl.MIPMAP_NONE,
+                                        USAGE_GRAPHICS_TEXTURE);
+    }
+
+    /**
+     * Creates an Allocation containing string data encoded in UTF-8 format.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param str string to create the allocation from
+     * @param usage bit field specifying how the allocaiton is
+     *              utilized
+     *
+     */
+    static public Allocation createFromString(RenderScript rs,
+                                              String str,
+                                              int usage) {
+        rs.validate();
+        byte[] allocArray = null;
+        try {
+            allocArray = str.getBytes("UTF-8");
+            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
+            alloc.copyFrom(allocArray);
+            return alloc;
+        }
+        catch (Exception e) {
+            throw new RSRuntimeException("Could not convert string to utf-8.");
+        }
+    }
+
+    /**
+     * Interface to handle notification when new buffers are available via
+     * {@link #USAGE_IO_INPUT}. An application will receive one notification
+     * when a buffer is available. Additional buffers will not trigger new
+     * notifications until a buffer is processed.
+     */
+    public interface OnBufferAvailableListener {
+        public void onBufferAvailable(Allocation a);
+    }
+
+    /**
+     * Set a notification handler for {@link #USAGE_IO_INPUT}.
+     *
+     * @param callback instance of the OnBufferAvailableListener
+     *                 class to be called when buffer arrive.
+     */
+    public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
+        synchronized(mAllocationMap) {
+            mAllocationMap.put(new Long(getID(mRS)), this);
+            mBufferNotifier = callback;
+        }
+    }
+
+    static void sendBufferNotification(long id) {
+        synchronized(mAllocationMap) {
+            Allocation a = mAllocationMap.get(new Long(id));
+
+            if ((a != null) && (a.mBufferNotifier != null)) {
+                a.mBufferNotifier.onBufferAvailable(a);
+            }
+        }
+    }
+
+    /**
+     * For USAGE_IO_OUTPUT, destroy() implies setSurface(null).
+     *
+     */
+    @Override
+    public void destroy() {
+        if((mUsage & USAGE_IO_OUTPUT) != 0) {
+            setSurface(null);
+        }
+
+        if (mType != null && mOwningType) {
+            mType.destroy();
+        }
+
+        super.destroy();
+    }
+
+}
diff --git a/android/renderscript/AllocationAdapter.java b/android/renderscript/AllocationAdapter.java
new file mode 100644
index 0000000..17bc234
--- /dev/null
+++ b/android/renderscript/AllocationAdapter.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Only intended for use by generated reflected code.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class AllocationAdapter extends Allocation {
+    Type mWindow;
+
+    AllocationAdapter(long id, RenderScript rs, Allocation alloc, Type t) {
+        super(id, rs, alloc.mType, alloc.mUsage);
+        mAdaptedAllocation = alloc;
+        mWindow = t;
+    }
+
+    /*
+    long getID(RenderScript rs) {
+        throw new RSInvalidStateException(
+            "This operation is not supported with adapters at this time.");
+    }
+    */
+
+    void initLOD(int lod) {
+        if (lod < 0) {
+            throw new RSIllegalArgumentException("Attempting to set negative lod (" + lod + ").");
+        }
+
+        int tx = mAdaptedAllocation.mType.getX();
+        int ty = mAdaptedAllocation.mType.getY();
+        int tz = mAdaptedAllocation.mType.getZ();
+
+        for (int ct=0; ct < lod; ct++) {
+            if ((tx==1) && (ty == 1) && (tz == 1)) {
+                throw new RSIllegalArgumentException("Attempting to set lod (" + lod + ") out of range.");
+            }
+
+            if (tx > 1) tx >>= 1;
+            if (ty > 1) ty >>= 1;
+            if (tz > 1) tz >>= 1;
+        }
+
+        mCurrentDimX = tx;
+        mCurrentDimY = ty;
+        mCurrentDimZ = tz;
+        mCurrentCount = mCurrentDimX;
+        if (mCurrentDimY > 1) {
+            mCurrentCount *= mCurrentDimY;
+        }
+        if (mCurrentDimZ > 1) {
+            mCurrentCount *= mCurrentDimZ;
+        }
+        mSelectedY = 0;
+        mSelectedZ = 0;
+    }
+
+    private void updateOffsets() {
+        int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
+
+        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);
+
+    }
+
+    /**
+     * Set the active LOD.  The LOD must be within the range for the
+     * type being adapted.  The base allocation must have mipmaps.
+     *
+     * Because this changes the dimensions of the adapter the
+     * current Y and Z will be reset.
+     *
+     * @param lod The LOD to make active.
+     */
+    public void setLOD(int lod) {
+        if (!mAdaptedAllocation.getType().hasMipmaps()) {
+            throw new RSInvalidStateException("Cannot set LOD when the allocation type does not include mipmaps.");
+        }
+        if (mWindow.hasMipmaps()) {
+            throw new RSInvalidStateException("Cannot set LOD when the adapter includes mipmaps.");
+        }
+
+        initLOD(lod);
+        mSelectedLOD = lod;
+        updateOffsets();
+    }
+
+    /**
+     * Set the active Face.  The base allocation must be of a type
+     * that includes faces.
+     *
+     * @param cf The face to make active.
+     */
+    public void setFace(Type.CubemapFace cf) {
+        if (!mAdaptedAllocation.getType().hasFaces()) {
+            throw new RSInvalidStateException("Cannot set Face when the allocation type does not include faces.");
+        }
+        if (mWindow.hasFaces()) {
+            throw new RSInvalidStateException("Cannot set face when the adapter includes faces.");
+        }
+        if (cf == null) {
+            throw new RSIllegalArgumentException("Cannot set null face.");
+        }
+
+        mSelectedFace = cf;
+        updateOffsets();
+    }
+
+
+    /**
+     *
+     * Set the active X.  The x value must be within the range for
+     * the allocation being adapted.
+     *
+     * @param x The x to make active.
+     */
+    public void setX(int x) {
+        if (mAdaptedAllocation.getType().getX() <= x) {
+            throw new RSInvalidStateException("Cannot set X greater than dimension of allocation.");
+        }
+        if (mWindow.getX() == mAdaptedAllocation.getType().getX()) {
+            throw new RSInvalidStateException("Cannot set X when the adapter includes X.");
+        }
+        if ((mWindow.getX() + x) >= mAdaptedAllocation.getType().getX()) {
+            throw new RSInvalidStateException("Cannot set (X + window) which would be larger than dimension of allocation.");
+        }
+
+        mSelectedX = x;
+        updateOffsets();
+    }
+
+    /**
+     * Set the active Y.  The y value must be within the range for
+     * the allocation being adapted.  The base allocation must
+     * contain the Y dimension.
+     *
+     * @param y The y to make active.
+     */
+    public void setY(int y) {
+        if (mAdaptedAllocation.getType().getY() == 0) {
+            throw new RSInvalidStateException("Cannot set Y when the allocation type does not include Y dim.");
+        }
+        if (mAdaptedAllocation.getType().getY() <= y) {
+            throw new RSInvalidStateException("Cannot set Y greater than dimension of allocation.");
+        }
+        if (mWindow.getY() == mAdaptedAllocation.getType().getY()) {
+            throw new RSInvalidStateException("Cannot set Y when the adapter includes Y.");
+        }
+        if ((mWindow.getY() + y) >= mAdaptedAllocation.getType().getY()) {
+            throw new RSInvalidStateException("Cannot set (Y + window) which would be larger than dimension of allocation.");
+        }
+
+        mSelectedY = y;
+        updateOffsets();
+    }
+
+    /**
+     * Set the active Z.  The z value must be within the range for
+     * the allocation being adapted.  The base allocation must
+     * contain the Z dimension.
+     *
+     * @param z The z to make active.
+     */
+    public void setZ(int z) {
+        if (mAdaptedAllocation.getType().getZ() == 0) {
+            throw new RSInvalidStateException("Cannot set Z when the allocation type does not include Z dim.");
+        }
+        if (mAdaptedAllocation.getType().getZ() <= z) {
+            throw new RSInvalidStateException("Cannot set Z greater than dimension of allocation.");
+        }
+        if (mWindow.getZ() == mAdaptedAllocation.getType().getZ()) {
+            throw new RSInvalidStateException("Cannot set Z when the adapter includes Z.");
+        }
+        if ((mWindow.getZ() + z) >= mAdaptedAllocation.getType().getZ()) {
+            throw new RSInvalidStateException("Cannot set (Z + window) which would be larger than dimension of allocation.");
+        }
+
+        mSelectedZ = z;
+        updateOffsets();
+    }
+
+    /**
+     * @hide
+     */
+    public void setArray(int arrayNum, int arrayVal) {
+        if (mAdaptedAllocation.getType().getArray(arrayNum) == 0) {
+            throw new RSInvalidStateException("Cannot set arrayNum when the allocation type does not include arrayNum dim.");
+        }
+        if (mAdaptedAllocation.getType().getArray(arrayNum) <= arrayVal) {
+            throw new RSInvalidStateException("Cannot set arrayNum greater than dimension of allocation.");
+        }
+        if (mWindow.getArray(arrayNum) == mAdaptedAllocation.getType().getArray(arrayNum)) {
+            throw new RSInvalidStateException("Cannot set arrayNum when the adapter includes arrayNum.");
+        }
+        if ((mWindow.getArray(arrayNum) + arrayVal) >= mAdaptedAllocation.getType().getArray(arrayNum)) {
+            throw new RSInvalidStateException("Cannot set (arrayNum + window) which would be larger than dimension of allocation.");
+        }
+
+        mSelectedArray[arrayNum] = arrayVal;
+        updateOffsets();
+    }
+
+    static public AllocationAdapter create1D(RenderScript rs, Allocation a) {
+        rs.validate();
+        Type t = Type.createX(rs, a.getElement(), a.getType().getX());
+        return createTyped(rs, a, t);
+    }
+
+
+    static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
+        rs.validate();
+        Type t = Type.createXY(rs, a.getElement(), a.getType().getX(), a.getType().getY());
+        return createTyped(rs, a, t);
+    }
+
+    /**
+     *
+     *
+     * Create an arbitrary window into the base allocation.
+     * The type describes the shape of the window.
+     *
+     * Any dimensions present in the type must be equal or smaller
+     * to the dimensions in the source allocation.  A dimension
+     * present in the allocation that is not present in the type
+     * will be constrained away with the selectors.
+     *
+     * If a dimension is present in both the type and allocation, one of
+     * two things will happen.
+     *
+     * If the type is smaller than the allocation, a window will be
+     * created, the selected value in the adapter for that dimension
+     * will act as the base address, and the type will describe the
+     * size of the view starting at that point.
+     *
+     * If the type and allocation dimension are of the same size,
+     * then setting the selector for the dimension will be an error.
+     */
+    static public AllocationAdapter createTyped(RenderScript rs, Allocation a, Type t) {
+        rs.validate();
+
+        if (a.mAdaptedAllocation != null) {
+            throw new RSInvalidStateException("Adapters cannot be nested.");
+        }
+
+        if (!a.getType().getElement().equals(t.getElement())) {
+            throw new RSInvalidStateException("Element must match Allocation type.");
+        }
+
+        if (t.hasFaces() || t.hasMipmaps()) {
+            throw new RSInvalidStateException("Adapters do not support window types with Mipmaps or Faces.");
+        }
+
+        Type at = a.getType();
+        if ((t.getX() > at.getX()) ||
+            (t.getY() > at.getY()) ||
+            (t.getZ() > at.getZ()) ||
+            (t.getArrayCount() > at.getArrayCount())) {
+
+            throw new RSInvalidStateException("Type cannot have dimension larger than the source allocation.");
+        }
+
+        if (t.getArrayCount() > 0) {
+            for (int i = 0; i < t.getArray(i); i++) {
+                if (t.getArray(i) > at.getArray(i)) {
+                    throw new RSInvalidStateException("Type cannot have dimension larger than the source allocation.");
+                }
+            }
+        }
+
+        // Create the object
+        long id = rs.nAllocationAdapterCreate(a.getID(rs), t.getID(rs));
+        if (id == 0) {
+            throw new RSRuntimeException("AllocationAdapter creation failed.");
+        }
+        return new AllocationAdapter(id, rs, a, t);
+    }
+
+    /**
+     * Override the Allocation resize.  Resizing adapters is not
+     * allowed and will throw a RSInvalidStateException.
+     *
+     * @param dimX ignored.
+     */
+    public synchronized void resize(int dimX) {
+        throw new RSInvalidStateException("Resize not allowed for Adapters.");
+    }
+
+}
+
+
diff --git a/android/renderscript/BaseObj.java b/android/renderscript/BaseObj.java
new file mode 100644
index 0000000..ea8535d
--- /dev/null
+++ b/android/renderscript/BaseObj.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+import dalvik.system.CloseGuard;
+
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * BaseObj is the base class for all RenderScript objects owned by a RS context.
+ * It is responsible for lifetime management and resource tracking. This class
+ * should not be used by a user application.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class BaseObj {
+    BaseObj(long id, RenderScript rs) {
+        rs.validate();
+        mRS = rs;
+        mID = id;
+        mDestroyed = false;
+    }
+
+    void setID(long id) {
+        if (mID != 0) {
+            throw new RSRuntimeException("Internal Error, reset of object ID.");
+        }
+        mID = id;
+    }
+
+    /**
+     * Lookup the native object ID for this object.  Primarily used by the
+     * generated reflected code.
+     *
+     * @param rs Context to verify against internal context for
+     *           match.
+     *
+     * @return long
+     */
+    long getID(RenderScript rs) {
+        mRS.validate();
+        if (mDestroyed) {
+            throw new RSInvalidStateException("using a destroyed object.");
+        }
+        if (mID == 0) {
+            throw new RSRuntimeException("Internal error: Object id 0.");
+        }
+        if ((rs != null) && (rs != mRS)) {
+            throw new RSInvalidStateException("using object with mismatched context.");
+        }
+        return mID;
+    }
+
+    void checkValid() {
+        if (mID == 0) {
+            throw new RSIllegalArgumentException("Invalid object.");
+        }
+    }
+
+    private long mID;
+    final CloseGuard guard = CloseGuard.get();
+    private boolean mDestroyed;
+    private String mName;
+    @UnsupportedAppUsage
+    RenderScript mRS;
+
+    /**
+     * setName assigns a name to an object.  This object can later be looked up
+     * by this name.
+     *
+     * @param name The name to assign to the object.
+     */
+    public void setName(String name) {
+        if (name == null) {
+            throw new RSIllegalArgumentException(
+                "setName requires a string of non-zero length.");
+        }
+        if(name.length() < 1) {
+            throw new RSIllegalArgumentException(
+                "setName does not accept a zero length string.");
+        }
+        if(mName != null) {
+            throw new RSIllegalArgumentException(
+                "setName object already has a name.");
+        }
+
+        try {
+            byte[] bytes = name.getBytes("UTF-8");
+            mRS.nAssignName(mID, bytes);
+            mName = name;
+        } catch (java.io.UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * @return name of the renderscript object
+     */
+    public String getName() {
+        return mName;
+    }
+
+    private void helpDestroy() {
+        boolean shouldDestroy = false;
+        synchronized(this) {
+            if (!mDestroyed) {
+                shouldDestroy = true;
+                mDestroyed = true;
+            }
+        }
+
+        if (shouldDestroy) {
+            guard.close();
+            // must include nObjDestroy in the critical section
+            ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
+            rlock.lock();
+            // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy
+            if(mRS.isAlive() && mID != 0) {
+                mRS.nObjDestroy(mID);
+            }
+            rlock.unlock();
+            mRS = null;
+            mID = 0;
+        }
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            if (guard != null) {
+                guard.warnIfOpen();
+            }
+            helpDestroy();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Frees any native resources associated with this object.  The
+     * primary use is to force immediate cleanup of resources when it is
+     * believed the GC will not respond quickly enough.
+     */
+    public void destroy() {
+        if(mDestroyed) {
+            throw new RSInvalidStateException("Object already destroyed.");
+        }
+        helpDestroy();
+    }
+
+    /**
+     * If an object came from an a3d file, java fields need to be
+     * created with objects from the native layer
+     */
+    void updateFromNative() {
+        mRS.validate();
+        mName = mRS.nGetName(getID(mRS));
+    }
+
+    /**
+     * Calculates the hash code value for a BaseObj.
+     *
+     * @return int
+     */
+    @Override
+    public int hashCode() {
+        return (int)((mID & 0xfffffff) ^ (mID >> 32));
+    }
+
+    /**
+     * Compare the current BaseObj with another BaseObj for equality.
+     *
+     * @param obj The object to check equality with.
+     *
+     * @return boolean
+     */
+    @Override
+    public boolean equals(Object obj) {
+        // Early-out check to see if both BaseObjs are actually the same
+        if (this == obj)
+            return true;
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        BaseObj b = (BaseObj) obj;
+        return mID == b.mID;
+    }
+}
+
diff --git a/android/renderscript/Byte2.java b/android/renderscript/Byte2.java
new file mode 100644
index 0000000..cb5cc47
--- /dev/null
+++ b/android/renderscript/Byte2.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Class for exposing the native RenderScript byte2 type back to the Android system.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Byte2 {
+    public byte x;
+    public byte y;
+
+    public Byte2() {
+    }
+
+    public Byte2(byte initX, byte initY) {
+        x = initX;
+        y = initY;
+    }
+
+    /** @hide */
+    public Byte2(Byte2 source) {
+        this.x = source.x;
+        this.y = source.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Byte2 a) {
+        this.x += a.x;
+        this.y += a.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 add(Byte2 a, Byte2 b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x + b.x);
+        result.y = (byte)(a.y + b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(byte value) {
+        x += value;
+        y += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 add(Byte2 a, byte b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x + b);
+        result.y = (byte)(a.y + b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Byte2 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 sub(Byte2 a, Byte2 b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x - b.x);
+        result.y = (byte)(a.y - b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(byte value) {
+        x -= value;
+        y -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 sub(Byte2 a, byte b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x - b);
+        result.y = (byte)(a.y - b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Byte2 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 mul(Byte2 a, Byte2 b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x * b.x);
+        result.y = (byte)(a.y * b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(byte value) {
+        x *= value;
+        y *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 mul(Byte2 a, byte b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x * b);
+        result.y = (byte)(a.y * b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Byte2 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 div(Byte2 a, Byte2 b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x / b.x);
+        result.y = (byte)(a.y / b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(byte value) {
+        x /= value;
+        y /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte2 div(Byte2 a, byte b) {
+        Byte2 result = new Byte2();
+        result.x = (byte)(a.x / b);
+        result.y = (byte)(a.y / b);
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public byte length() {
+        return 2;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = (byte)(-x);
+        this.y = (byte)(-y);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public byte dotProduct(Byte2 a) {
+        return (byte)((x * a.x) + (y * a.y));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static byte dotProduct(Byte2 a, Byte2 b) {
+        return (byte)((b.x * a.x) + (b.y * a.y));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Byte2 a, byte factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+    }
+
+    /** @hide
+     * set vector value by Byte2
+     *
+     * @param a
+     */
+    public void set(Byte2 a) {
+        this.x = a.x;
+        this.y = a.y;
+    }
+
+    /** @hide
+     * set the vector field value by Char
+     *
+     * @param a
+     * @param b
+     */
+    public void setValues(byte a, byte b) {
+        this.x = a;
+        this.y = b;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public byte elementSum() {
+        return (byte)(x + y);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public byte get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, byte value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, byte value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to Char array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(byte[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+    }
+
+}
+
+
+
+
diff --git a/android/renderscript/Byte3.java b/android/renderscript/Byte3.java
new file mode 100644
index 0000000..aca4e64
--- /dev/null
+++ b/android/renderscript/Byte3.java
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Class for exposing the native RenderScript byte3 type back to the Android system.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Byte3 {
+    public byte x;
+    public byte y;
+    public byte z;
+
+    public Byte3() {
+    }
+
+    public Byte3(byte initX, byte initY, byte initZ) {
+        x = initX;
+        y = initY;
+        z = initZ;
+    }
+
+    /** @hide */
+    public Byte3(Byte3 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Byte3 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 add(Byte3 a, Byte3 b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x + b.x);
+        result.y = (byte)(a.y + b.y);
+        result.z = (byte)(a.z + b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(byte value) {
+        x += value;
+        y += value;
+        z += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 add(Byte3 a, byte b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x + b);
+        result.y = (byte)(a.y + b);
+        result.z = (byte)(a.z + b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Byte3 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 sub(Byte3 a, Byte3 b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x - b.x);
+        result.y = (byte)(a.y - b.y);
+        result.z = (byte)(a.z - b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(byte value) {
+        x -= value;
+        y -= value;
+        z -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 sub(Byte3 a, byte b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x - b);
+        result.y = (byte)(a.y - b);
+        result.z = (byte)(a.z - b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Byte3 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 mul(Byte3 a, Byte3 b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x * b.x);
+        result.y = (byte)(a.y * b.y);
+        result.z = (byte)(a.z * b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(byte value) {
+        x *= value;
+        y *= value;
+        z *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 mul(Byte3 a, byte b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x * b);
+        result.y = (byte)(a.y * b);
+        result.z = (byte)(a.z * b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Byte3 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 div(Byte3 a, Byte3 b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x / b.x);
+        result.y = (byte)(a.y / b.y);
+        result.z = (byte)(a.z / b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(byte value) {
+        x /= value;
+        y /= value;
+        z /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte3 div(Byte3 a, byte b) {
+        Byte3 result = new Byte3();
+        result.x = (byte)(a.x / b);
+        result.y = (byte)(a.y / b);
+        result.z = (byte)(a.z / b);
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public byte length() {
+        return 3;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = (byte)(-x);
+        this.y = (byte)(-y);
+        this.z = (byte)(-z);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public byte dotProduct(Byte3 a) {
+        return (byte)((byte)((byte)(x * a.x) + (byte)(y * a.y)) + (byte)(z * a.z));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static byte dotProduct(Byte3 a, Byte3 b) {
+        return (byte)((byte)((byte)(b.x * a.x) + (byte)(b.y * a.y)) + (byte)(b.z * a.z));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Byte3 a, byte factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+    }
+
+    /** @hide
+     * set vector value by Byte3
+     *
+     * @param a
+     */
+    public void set(Byte3 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+    }
+
+    /** @hide
+     * set the vector field value by Char
+     *
+     * @param a
+     * @param b
+     * @param c
+     */
+    public void setValues(byte a, byte b, byte c) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public byte elementSum() {
+        return (byte)(x + y + z);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public byte get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        case 2:
+            return z;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, byte value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, byte value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to Char array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(byte[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+        data[offset + 2] = z;
+    }
+}
+
+
+
+
diff --git a/android/renderscript/Byte4.java b/android/renderscript/Byte4.java
new file mode 100644
index 0000000..b30b6ed
--- /dev/null
+++ b/android/renderscript/Byte4.java
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Class for exposing the native RenderScript byte4 type back to the Android system.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Byte4 {
+    public byte x;
+    public byte y;
+    public byte z;
+    public byte w;
+
+    public Byte4() {
+    }
+
+    public Byte4(byte initX, byte initY, byte initZ, byte initW) {
+        x = initX;
+        y = initY;
+        z = initZ;
+        w = initW;
+    }
+    /** @hide */
+    public Byte4(Byte4 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+        this.w = source.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Byte4 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+        this.w += a.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 add(Byte4 a, Byte4 b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x + b.x);
+        result.y = (byte)(a.y + b.y);
+        result.z = (byte)(a.z + b.z);
+        result.w = (byte)(a.w + b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(byte value) {
+        x += value;
+        y += value;
+        z += value;
+        w += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 add(Byte4 a, byte b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x + b);
+        result.y = (byte)(a.y + b);
+        result.z = (byte)(a.z + b);
+        result.w = (byte)(a.w + b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Byte4 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+        this.w -= a.w;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 sub(Byte4 a, Byte4 b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x - b.x);
+        result.y = (byte)(a.y - b.y);
+        result.z = (byte)(a.z - b.z);
+        result.w = (byte)(a.w - b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(byte value) {
+        x -= value;
+        y -= value;
+        z -= value;
+        w -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 sub(Byte4 a, byte b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x - b);
+        result.y = (byte)(a.y - b);
+        result.z = (byte)(a.z - b);
+        result.w = (byte)(a.w - b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Byte4 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+        this.w *= a.w;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 mul(Byte4 a, Byte4 b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x * b.x);
+        result.y = (byte)(a.y * b.y);
+        result.z = (byte)(a.z * b.z);
+        result.w = (byte)(a.w * b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(byte value) {
+        x *= value;
+        y *= value;
+        z *= value;
+        w *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 mul(Byte4 a, byte b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x * b);
+        result.y = (byte)(a.y * b);
+        result.z = (byte)(a.z * b);
+        result.w = (byte)(a.w * b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Byte4 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+        this.w /= a.w;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 div(Byte4 a, Byte4 b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x / b.x);
+        result.y = (byte)(a.y / b.y);
+        result.z = (byte)(a.z / b.z);
+        result.w = (byte)(a.w / b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(byte value) {
+        x /= value;
+        y /= value;
+        z /= value;
+        w /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Byte4 div(Byte4 a, byte b) {
+        Byte4 result = new Byte4();
+        result.x = (byte)(a.x / b);
+        result.y = (byte)(a.y / b);
+        result.z = (byte)(a.z / b);
+        result.w = (byte)(a.w / b);
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public byte length() {
+        return 4;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = (byte)(-x);
+        this.y = (byte)(-y);
+        this.z = (byte)(-z);
+        this.w = (byte)(-w);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public byte dotProduct(Byte4 a) {
+        return (byte)((x * a.x) + (y * a.y) + (z * a.z) + (w * a.w));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static byte dotProduct(Byte4 a, Byte4 b) {
+        return (byte)((b.x * a.x) + (b.y * a.y) + (b.z * a.z) + (b.w * a.w));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Byte4 a, byte factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+        w += a.w * factor;
+    }
+
+    /** @hide
+     * set vector value by Byte4
+     *
+     * @param a
+     */
+    public void set(Byte4 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+        this.w = a.w;
+    }
+
+    /** @hide
+     * set the vector field values
+     *
+     * @param a
+     * @param b
+     * @param c
+     * @param d
+     */
+    public void setValues(byte a, byte b, byte c, byte d) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+        this.w = d;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public byte elementSum() {
+        return (byte)(x + y + z + w);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public byte get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        case 2:
+            return z;
+        case 3:
+            return w;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, byte value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        case 3:
+            w = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, byte value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        case 3:
+            w += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to Char array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(byte[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+        data[offset + 2] = z;
+        data[offset + 3] = w;
+    }
+}
+
+
+
diff --git a/android/renderscript/Double2.java b/android/renderscript/Double2.java
new file mode 100644
index 0000000..e14228a
--- /dev/null
+++ b/android/renderscript/Double2.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic double type.
+ * Provides two double fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Double2 {
+    public double x;
+    public double y;
+
+    public Double2() {
+    }
+
+    /** @hide */
+    public Double2(Double2 data) {
+        this.x = data.x;
+        this.y = data.y;
+    }
+
+    public Double2(double x, double y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 add(Double2 a, Double2 b) {
+        Double2 res = new Double2();
+        res.x = a.x + b.x;
+        res.y = a.y + b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(Double2 value) {
+        x += value.x;
+        y += value.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(double value) {
+        x += value;
+        y += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 add(Double2 a, double b) {
+        Double2 res = new Double2();
+        res.x = a.x + b;
+        res.y = a.y + b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(Double2 value) {
+        x -= value.x;
+        y -= value.y;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 sub(Double2 a, Double2 b) {
+        Double2 res = new Double2();
+        res.x = a.x - b.x;
+        res.y = a.y - b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(double value) {
+        x -= value;
+        y -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 sub(Double2 a, double b) {
+        Double2 res = new Double2();
+        res.x = a.x - b;
+        res.y = a.y - b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(Double2 value) {
+        x *= value.x;
+        y *= value.y;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 mul(Double2 a, Double2 b) {
+        Double2 res = new Double2();
+        res.x = a.x * b.x;
+        res.y = a.y * b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(double value) {
+        x *= value;
+        y *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 mul(Double2 a, double b) {
+        Double2 res = new Double2();
+        res.x = a.x * b;
+        res.y = a.y * b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(Double2 value) {
+        x /= value.x;
+        y /= value.y;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 div(Double2 a, Double2 b) {
+        Double2 res = new Double2();
+        res.x = a.x / b.x;
+        res.y = a.y / b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(double value) {
+        x /= value;
+        y /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double2 div(Double2 a, double b) {
+        Double2 res = new Double2();
+        res.x = a.x / b;
+        res.y = a.y / b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public double dotProduct(Double2 a) {
+        return (x * a.x) + (y * a.y);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double dotProduct(Double2 a, Double2 b) {
+        return (b.x * a.x) + (b.y * a.y);
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Double2 a, double factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+    }
+
+    /** @hide
+     * Set vector value by double2
+     *
+     * @param a
+     */
+    public void set(Double2 a) {
+        this.x = a.x;
+        this.y = a.y;
+    }
+
+    /** @hide
+     * Set vector negate
+     */
+    public void negate() {
+        x = -x;
+        y = -y;
+    }
+
+    /** @hide
+     * Get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 2;
+    }
+
+    /** @hide
+     * Return the element sum of vector
+     *
+     * @return
+     */
+    public double elementSum() {
+        return x + y;
+    }
+
+    /** @hide
+     * Get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public double get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, double value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, double value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Set the vector field value
+     *
+     * @param x
+     * @param y
+     */
+    public void setValues(double x, double y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide
+     * Copy the vector to double array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(double[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+    }
+}
diff --git a/android/renderscript/Double3.java b/android/renderscript/Double3.java
new file mode 100644
index 0000000..e52c902
--- /dev/null
+++ b/android/renderscript/Double3.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic double type.
+ * Provides three double fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Double3 {
+    public double x;
+    public double y;
+    public double z;
+
+    public Double3() {
+    }
+    /** @hide */
+    public Double3(Double3 data) {
+        this.x = data.x;
+        this.y = data.y;
+        this.z = data.z;
+    }
+
+    public Double3(double x, double y, double z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 add(Double3 a, Double3 b) {
+        Double3 res = new Double3();
+        res.x = a.x + b.x;
+        res.y = a.y + b.y;
+        res.z = a.z + b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(Double3 value) {
+        x += value.x;
+        y += value.y;
+        z += value.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(double value) {
+        x += value;
+        y += value;
+        z += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 add(Double3 a, double b) {
+        Double3 res = new Double3();
+        res.x = a.x + b;
+        res.y = a.y + b;
+        res.z = a.z + b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(Double3 value) {
+        x -= value.x;
+        y -= value.y;
+        z -= value.z;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 sub(Double3 a, Double3 b) {
+        Double3 res = new Double3();
+        res.x = a.x - b.x;
+        res.y = a.y - b.y;
+        res.z = a.z - b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(double value) {
+        x -= value;
+        y -= value;
+        z -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 sub(Double3 a, double b) {
+        Double3 res = new Double3();
+        res.x = a.x - b;
+        res.y = a.y - b;
+        res.z = a.z - b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(Double3 value) {
+        x *= value.x;
+        y *= value.y;
+        z *= value.z;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 mul(Double3 a, Double3 b) {
+        Double3 res = new Double3();
+        res.x = a.x * b.x;
+        res.y = a.y * b.y;
+        res.z = a.z * b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(double value) {
+        x *= value;
+        y *= value;
+        z *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 mul(Double3 a, double b) {
+        Double3 res = new Double3();
+        res.x = a.x * b;
+        res.y = a.y * b;
+        res.z = a.z * b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(Double3 value) {
+        x /= value.x;
+        y /= value.y;
+        z /= value.z;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 div(Double3 a, Double3 b) {
+        Double3 res = new Double3();
+        res.x = a.x / b.x;
+        res.y = a.y / b.y;
+        res.z = a.z / b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(double value) {
+        x /= value;
+        y /= value;
+        z /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double3 div(Double3 a, double b) {
+        Double3 res = new Double3();
+        res.x = a.x / b;
+        res.y = a.y / b;
+        res.z = a.z / b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public double dotProduct(Double3 a) {
+        return (x * a.x) + (y * a.y) + (z * a.z);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static double dotProduct(Double3 a, Double3 b) {
+        return (b.x * a.x) + (b.y * a.y) + (b.z * a.z);
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Double3 a, double factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+    }
+
+    /** @hide
+     * Set vector value by double3
+     *
+     * @param a
+     */
+    public void set(Double3 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+    }
+
+    /** @hide
+     * Set vector negate
+     */
+    public void negate() {
+        x = -x;
+        y = -y;
+        z = -z;
+    }
+
+    /** @hide
+     * Get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 3;
+    }
+
+    /** @hide
+     * Return the element sum of vector
+     *
+     * @return
+     */
+    public double elementSum() {
+        return x + y + z;
+    }
+
+    /** @hide
+     * Get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public double get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        case 2:
+            return z;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, double value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, double value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Set the vector field value
+     *
+     * @param x
+     * @param y
+     * @param z
+     */
+    public void setValues(double x, double y, double z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide
+     * Copy the vector to double array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(double[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+        data[offset + 2] = z;
+    }
+}
diff --git a/android/renderscript/Double4.java b/android/renderscript/Double4.java
new file mode 100644
index 0000000..a3e4a94
--- /dev/null
+++ b/android/renderscript/Double4.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic double type.
+ * Provides four double fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Double4 {
+    public double x;
+    public double y;
+    public double z;
+    public double w;
+
+    public Double4() {
+    }
+    /** @hide */
+    public Double4(Double4 data) {
+        this.x = data.x;
+        this.y = data.y;
+        this.z = data.z;
+        this.w = data.w;
+    }
+
+    public Double4(double x, double y, double z, double w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 add(Double4 a, Double4 b) {
+        Double4 res = new Double4();
+        res.x = a.x + b.x;
+        res.y = a.y + b.y;
+        res.z = a.z + b.z;
+        res.w = a.w + b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(Double4 value) {
+        x += value.x;
+        y += value.y;
+        z += value.z;
+        w += value.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(double value) {
+        x += value;
+        y += value;
+        z += value;
+        w += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 add(Double4 a, double b) {
+        Double4 res = new Double4();
+        res.x = a.x + b;
+        res.y = a.y + b;
+        res.z = a.z + b;
+        res.w = a.w + b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(Double4 value) {
+        x -= value.x;
+        y -= value.y;
+        z -= value.z;
+        w -= value.w;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(double value) {
+        x -= value;
+        y -= value;
+        z -= value;
+        w -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 sub(Double4 a, double b) {
+        Double4 res = new Double4();
+        res.x = a.x - b;
+        res.y = a.y - b;
+        res.z = a.z - b;
+        res.w = a.w - b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 sub(Double4 a, Double4 b) {
+        Double4 res = new Double4();
+        res.x = a.x - b.x;
+        res.y = a.y - b.y;
+        res.z = a.z - b.z;
+        res.w = a.w - b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(Double4 value) {
+        x *= value.x;
+        y *= value.y;
+        z *= value.z;
+        w *= value.w;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(double value) {
+        x *= value;
+        y *= value;
+        z *= value;
+        w *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 mul(Double4 a, Double4 b) {
+        Double4 res = new Double4();
+        res.x = a.x * b.x;
+        res.y = a.y * b.y;
+        res.z = a.z * b.z;
+        res.w = a.w * b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 mul(Double4 a, double b) {
+        Double4 res = new Double4();
+        res.x = a.x * b;
+        res.y = a.y * b;
+        res.z = a.z * b;
+        res.w = a.w * b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(Double4 value) {
+        x /= value.x;
+        y /= value.y;
+        z /= value.z;
+        w /= value.w;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(double value) {
+        x /= value;
+        y /= value;
+        z /= value;
+        w /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 div(Double4 a, double b) {
+        Double4 res = new Double4();
+        res.x = a.x / b;
+        res.y = a.y / b;
+        res.z = a.z / b;
+        res.w = a.w / b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Double4 div(Double4 a, Double4 b) {
+        Double4 res = new Double4();
+        res.x = a.x / b.x;
+        res.y = a.y / b.y;
+        res.z = a.z / b.z;
+        res.w = a.w / b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public double dotProduct(Double4 a) {
+        return (x * a.x) + (y * a.y) + (z * a.z) + (w * a.w);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static double dotProduct(Double4 a, Double4 b) {
+        return (b.x * a.x) + (b.y * a.y) + (b.z * a.z) + (b.w * a.w);
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Double4 a, double factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+        w += a.w * factor;
+    }
+
+    /** @hide
+     * Set vector value by double4
+     *
+     * @param a
+     */
+    public void set(Double4 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+        this.w = a.w;
+    }
+
+    /** @hide
+     * Set vector negate
+     */
+    public void negate() {
+        x = -x;
+        y = -y;
+        z = -z;
+        w = -w;
+    }
+
+    /** @hide
+     * Get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 4;
+    }
+
+    /** @hide
+     * Return the element sum of vector
+     *
+     * @return
+     */
+    public double elementSum() {
+        return x + y + z + w;
+    }
+
+    /** @hide
+     * Get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public double get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        case 2:
+            return z;
+        case 3:
+            return w;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, double value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        case 3:
+            w = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, double value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        case 3:
+            w += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * Set the vector field value
+     *
+     * @param x
+     * @param y
+     * @param z
+     * @param w
+     */
+    public void setValues(double x, double y, double z, double w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide
+     * Copy the vector to double array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(double[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+        data[offset + 2] = z;
+        data[offset + 3] = w;
+    }
+}
diff --git a/android/renderscript/Element.java b/android/renderscript/Element.java
new file mode 100644
index 0000000..f671953
--- /dev/null
+++ b/android/renderscript/Element.java
@@ -0,0 +1,1406 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+/**
+ * <p>An Element represents one item within an {@link
+ * android.renderscript.Allocation}.  An Element is roughly equivalent to a C
+ * type in a RenderScript kernel. Elements may be basic or complex. Some basic
+ * elements are</p> <ul> <li>A single float value (equivalent to a float in a
+ * kernel)</li> <li>A four-element float vector (equivalent to a float4 in a
+ * kernel)</li> <li>An unsigned 32-bit integer (equivalent to an unsigned int in
+ * a kernel)</li> <li>A single signed 8-bit integer (equivalent to a char in a
+ * kernel)</li> </ul> <p>A complex element is roughly equivalent to a C struct
+ * and contains a number of basic or complex Elements. From Java code, a complex
+ * element contains a list of sub-elements and names that represents a
+ * particular data structure. Structs used in RS scripts are available to Java
+ * code by using the {@code ScriptField_structname} class that is reflected from
+ * a particular script.</p>
+ *
+ * <p>Basic Elements are comprised of a {@link
+ * android.renderscript.Element.DataType} and a {@link
+ * android.renderscript.Element.DataKind}. The DataType encodes C type
+ * information of an Element, while the DataKind encodes how that Element should
+ * be interpreted by a {@link android.renderscript.Sampler}. Note that {@link
+ * android.renderscript.Allocation} objects with DataKind {@link
+ * android.renderscript.Element.DataKind#USER} cannot be used as input for a
+ * {@link android.renderscript.Sampler}. In general, {@link
+ * android.renderscript.Allocation} objects that are intended for use with a
+ * {@link android.renderscript.Sampler} should use bitmap-derived Elements such
+ * as {@link android.renderscript.Element#RGBA_8888} or {@link
+ * android.renderscript#Element.A_8}.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Element extends BaseObj {
+    int mSize;
+    Element[] mElements;
+    String[] mElementNames;
+    int[] mArraySizes;
+    int[] mOffsetInBytes;
+
+    int[] mVisibleElementMap;
+
+    DataType mType;
+    DataKind mKind;
+    boolean mNormalized;
+    int mVectorSize;
+
+    private void updateVisibleSubElements() {
+        if (mElements == null) {
+            return;
+        }
+
+        int noPaddingFieldCount = 0;
+        int fieldCount = mElementNames.length;
+        // Find out how many elements are not padding
+        for (int ct = 0; ct < fieldCount; ct ++) {
+            if (mElementNames[ct].charAt(0) != '#') {
+                noPaddingFieldCount ++;
+            }
+        }
+        mVisibleElementMap = new int[noPaddingFieldCount];
+
+        // Make a map that points us at non-padding elements
+        for (int ct = 0, ctNoPadding = 0; ct < fieldCount; ct ++) {
+            if (mElementNames[ct].charAt(0) != '#') {
+                mVisibleElementMap[ctNoPadding ++] = ct;
+            }
+        }
+    }
+
+    /**
+    * @return element size in bytes
+    */
+    public int getBytesSize() {return mSize;}
+
+    /**
+    * Returns the number of vector components. 2 for float2, 4 for
+    * float4, etc.
+    * @return element vector size
+    */
+    public int getVectorSize() {return mVectorSize;}
+
+
+    /**
+     * DataType represents the basic type information for a basic element.  The
+     * naming convention follows.  For numeric types it is FLOAT,
+     * SIGNED, or UNSIGNED followed by the _BITS where BITS is the
+     * size of the data.  BOOLEAN is a true / false (1,0)
+     * represented in an 8 bit container.  The UNSIGNED variants
+     * with multiple bit definitions are for packed graphical data
+     * formats and represent vectors with per vector member sizes
+     * which are treated as a single unit for packing and alignment
+     * purposes.
+     *
+     * MATRIX the three matrix types contain FLOAT_32 elements and are treated
+     * as 32 bits for alignment purposes.
+     *
+     * RS_* objects:  opaque handles with implementation dependent
+     * sizes.
+     */
+    public enum DataType {
+        NONE (0, 0),
+        FLOAT_16 (1, 2),
+        FLOAT_32 (2, 4),
+        FLOAT_64 (3, 8),
+        SIGNED_8 (4, 1),
+        SIGNED_16 (5, 2),
+        SIGNED_32 (6, 4),
+        SIGNED_64 (7, 8),
+        UNSIGNED_8 (8, 1),
+        UNSIGNED_16 (9, 2),
+        UNSIGNED_32 (10, 4),
+        UNSIGNED_64 (11, 8),
+
+        BOOLEAN(12, 1),
+
+        UNSIGNED_5_6_5 (13, 2),
+        UNSIGNED_5_5_5_1 (14, 2),
+        UNSIGNED_4_4_4_4 (15, 2),
+
+        MATRIX_4X4 (16, 64),
+        MATRIX_3X3 (17, 36),
+        MATRIX_2X2 (18, 16),
+
+        RS_ELEMENT (1000),
+        RS_TYPE (1001),
+        RS_ALLOCATION (1002),
+        RS_SAMPLER (1003),
+        RS_SCRIPT (1004),
+        RS_MESH (1005),
+        RS_PROGRAM_FRAGMENT (1006),
+        RS_PROGRAM_VERTEX (1007),
+        RS_PROGRAM_RASTER (1008),
+        RS_PROGRAM_STORE (1009),
+        RS_FONT (1010);
+
+        int mID;
+        int mSize;
+        DataType(int id, int size) {
+            mID = id;
+            mSize = size;
+        }
+
+        DataType(int id) {
+            mID = id;
+            mSize = 4;
+            if (RenderScript.sPointerSize == 8) {
+                mSize = 32;
+            }
+        }
+    }
+
+    /**
+     * The special interpretation of the data if required.  This is primarly
+     * useful for graphical data.  USER indicates no special interpretation is
+     * expected.  PIXEL is used in conjunction with the standard data types for
+     * representing texture formats.
+     */
+    public enum DataKind {
+        USER (0),
+
+        PIXEL_L (7),
+        PIXEL_A (8),
+        PIXEL_LA (9),
+        PIXEL_RGB (10),
+        PIXEL_RGBA (11),
+        PIXEL_DEPTH (12),
+        PIXEL_YUV(13);
+
+        int mID;
+        DataKind(int id) {
+            mID = id;
+        }
+    }
+
+    /**
+     * Return if a element is too complex for use as a data source for a Mesh or
+     * a Program.
+     *
+     * @return boolean
+     */
+    public boolean isComplex() {
+        if (mElements == null) {
+            return false;
+        }
+        for (int ct=0; ct < mElements.length; ct++) {
+            if (mElements[ct].mElements != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+    * Elements could be simple, such as an int or a float, or a
+    * structure with multiple sub elements, such as a collection of
+    * floats, float2, float4. This function returns zero for simple
+    * elements or the number of sub-elements otherwise.
+    * @return number of sub-elements in this element
+    */
+    public int getSubElementCount() {
+        if (mVisibleElementMap == null) {
+            return 0;
+        }
+        return mVisibleElementMap.length;
+    }
+
+    /**
+    * For complex elements, this function will return the
+    * sub-element at index
+    * @param index index of the sub-element to return
+    * @return sub-element in this element at given index
+    */
+    public Element getSubElement(int index) {
+        if (mVisibleElementMap == null) {
+            throw new RSIllegalArgumentException("Element contains no sub-elements");
+        }
+        if (index < 0 || index >= mVisibleElementMap.length) {
+            throw new RSIllegalArgumentException("Illegal sub-element index");
+        }
+        return mElements[mVisibleElementMap[index]];
+    }
+
+    /**
+    * For complex elements, this function will return the
+    * sub-element name at index
+    * @param index index of the sub-element
+    * @return sub-element in this element at given index
+    */
+    public String getSubElementName(int index) {
+        if (mVisibleElementMap == null) {
+            throw new RSIllegalArgumentException("Element contains no sub-elements");
+        }
+        if (index < 0 || index >= mVisibleElementMap.length) {
+            throw new RSIllegalArgumentException("Illegal sub-element index");
+        }
+        return mElementNames[mVisibleElementMap[index]];
+    }
+
+    /**
+    * For complex elements, some sub-elements could be statically
+    * sized arrays. This function will return the array size for
+    * sub-element at index
+    * @param index index of the sub-element
+    * @return array size of sub-element in this element at given index
+    */
+    public int getSubElementArraySize(int index) {
+        if (mVisibleElementMap == null) {
+            throw new RSIllegalArgumentException("Element contains no sub-elements");
+        }
+        if (index < 0 || index >= mVisibleElementMap.length) {
+            throw new RSIllegalArgumentException("Illegal sub-element index");
+        }
+        return mArraySizes[mVisibleElementMap[index]];
+    }
+
+    /**
+    * This function specifies the location of a sub-element within
+    * the element
+    * @param index index of the sub-element
+    * @return offset in bytes of sub-element in this element at given index
+    */
+    public int getSubElementOffsetBytes(int index) {
+        if (mVisibleElementMap == null) {
+            throw new RSIllegalArgumentException("Element contains no sub-elements");
+        }
+        if (index < 0 || index >= mVisibleElementMap.length) {
+            throw new RSIllegalArgumentException("Illegal sub-element index");
+        }
+        return mOffsetInBytes[mVisibleElementMap[index]];
+    }
+
+    /**
+    * @return element data type
+    */
+    public DataType getDataType() {
+        return mType;
+    }
+
+    /**
+    * @return element data kind
+    */
+    public DataKind getDataKind() {
+        return mKind;
+    }
+
+    /**
+     * Utility function for returning an Element containing a single Boolean.
+     *
+     * @param rs Context to which the element will belong.
+     *
+     * @return Element
+     */
+    public static Element BOOLEAN(RenderScript rs) {
+        if (rs.mElement_BOOLEAN == null) {
+            synchronized (rs) {
+                if (rs.mElement_BOOLEAN == null) {
+                    rs.mElement_BOOLEAN = createUser(rs, DataType.BOOLEAN);
+                }
+            }
+        }
+        return rs.mElement_BOOLEAN;
+    }
+
+    /**
+     * Utility function for returning an Element containing a single UNSIGNED_8.
+     *
+     * @param rs Context to which the element will belong.
+     *
+     * @return Element
+     */
+    public static Element U8(RenderScript rs) {
+        if (rs.mElement_U8 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U8 == null) {
+                    rs.mElement_U8 = createUser(rs, DataType.UNSIGNED_8);
+                }
+            }
+        }
+        return rs.mElement_U8;
+    }
+
+    /**
+     * Utility function for returning an Element containing a single SIGNED_8.
+     *
+     * @param rs Context to which the element will belong.
+     *
+     * @return Element
+     */
+    public static Element I8(RenderScript rs) {
+        if (rs.mElement_I8 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I8 == null) {
+                    rs.mElement_I8 = createUser(rs, DataType.SIGNED_8);
+                }
+            }
+        }
+        return rs.mElement_I8;
+    }
+
+    public static Element U16(RenderScript rs) {
+        if (rs.mElement_U16 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U16 == null) {
+                    rs.mElement_U16 = createUser(rs, DataType.UNSIGNED_16);
+                }
+            }
+        }
+        return rs.mElement_U16;
+    }
+
+    public static Element I16(RenderScript rs) {
+        if (rs.mElement_I16 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I16 == null) {
+                    rs.mElement_I16 = createUser(rs, DataType.SIGNED_16);
+                }
+            }
+        }
+        return rs.mElement_I16;
+    }
+
+    public static Element U32(RenderScript rs) {
+        if (rs.mElement_U32 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U32 == null) {
+                    rs.mElement_U32 = createUser(rs, DataType.UNSIGNED_32);
+                }
+            }
+        }
+        return rs.mElement_U32;
+    }
+
+    public static Element I32(RenderScript rs) {
+        if (rs.mElement_I32 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I32 == null) {
+                    rs.mElement_I32 = createUser(rs, DataType.SIGNED_32);
+                }
+            }
+        }
+        return rs.mElement_I32;
+    }
+
+    public static Element U64(RenderScript rs) {
+        if (rs.mElement_U64 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U64 == null) {
+                    rs.mElement_U64 = createUser(rs, DataType.UNSIGNED_64);
+                }
+            }
+        }
+        return rs.mElement_U64;
+    }
+
+    public static Element I64(RenderScript rs) {
+        if (rs.mElement_I64 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I64 == null) {
+                    rs.mElement_I64 = createUser(rs, DataType.SIGNED_64);
+                }
+            }
+        }
+        return rs.mElement_I64;
+    }
+
+    public static Element F16(RenderScript rs) {
+        if (rs.mElement_F16 == null) {
+            synchronized (rs) {
+                if (rs.mElement_F16 == null) {
+                    rs.mElement_F16 = createUser(rs, DataType.FLOAT_16);
+                }
+            }
+        }
+        return rs.mElement_F16;
+    }
+
+    public static Element F32(RenderScript rs) {
+        if (rs.mElement_F32 == null) {
+            synchronized (rs) {
+                if (rs.mElement_F32 == null) {
+                    rs.mElement_F32 = createUser(rs, DataType.FLOAT_32);
+                }
+            }
+        }
+        return rs.mElement_F32;
+    }
+
+    public static Element F64(RenderScript rs) {
+        if (rs.mElement_F64 == null) {
+            synchronized (rs) {
+                if (rs.mElement_F64 == null) {
+                    rs.mElement_F64 = createUser(rs, DataType.FLOAT_64);
+                }
+            }
+        }
+        return rs.mElement_F64;
+    }
+
+    public static Element ELEMENT(RenderScript rs) {
+        if (rs.mElement_ELEMENT == null) {
+            synchronized (rs) {
+                if (rs.mElement_ELEMENT == null) {
+                    rs.mElement_ELEMENT = createUser(rs, DataType.RS_ELEMENT);
+                }
+            }
+        }
+        return rs.mElement_ELEMENT;
+    }
+
+    public static Element TYPE(RenderScript rs) {
+        if (rs.mElement_TYPE == null) {
+            synchronized (rs) {
+                if (rs.mElement_TYPE == null) {
+                    rs.mElement_TYPE = createUser(rs, DataType.RS_TYPE);
+                }
+            }
+        }
+        return rs.mElement_TYPE;
+    }
+
+    public static Element ALLOCATION(RenderScript rs) {
+        if (rs.mElement_ALLOCATION == null) {
+            synchronized (rs) {
+                if (rs.mElement_ALLOCATION == null) {
+                    rs.mElement_ALLOCATION = createUser(rs, DataType.RS_ALLOCATION);
+                }
+            }
+        }
+        return rs.mElement_ALLOCATION;
+    }
+
+    public static Element SAMPLER(RenderScript rs) {
+        if (rs.mElement_SAMPLER == null) {
+            synchronized (rs) {
+                if (rs.mElement_SAMPLER == null) {
+                    rs.mElement_SAMPLER = createUser(rs, DataType.RS_SAMPLER);
+                }
+            }
+        }
+        return rs.mElement_SAMPLER;
+    }
+
+    public static Element SCRIPT(RenderScript rs) {
+        if (rs.mElement_SCRIPT == null) {
+            synchronized (rs) {
+                if (rs.mElement_SCRIPT == null) {
+                    rs.mElement_SCRIPT = createUser(rs, DataType.RS_SCRIPT);
+                }
+            }
+        }
+        return rs.mElement_SCRIPT;
+    }
+
+    public static Element MESH(RenderScript rs) {
+        if (rs.mElement_MESH == null) {
+            synchronized (rs) {
+                if (rs.mElement_MESH == null) {
+                    rs.mElement_MESH = createUser(rs, DataType.RS_MESH);
+                }
+            }
+        }
+        return rs.mElement_MESH;
+    }
+
+    public static Element PROGRAM_FRAGMENT(RenderScript rs) {
+        if (rs.mElement_PROGRAM_FRAGMENT == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_FRAGMENT == null) {
+                    rs.mElement_PROGRAM_FRAGMENT = createUser(rs, DataType.RS_PROGRAM_FRAGMENT);
+                }
+            }
+        }
+        return rs.mElement_PROGRAM_FRAGMENT;
+    }
+
+    public static Element PROGRAM_VERTEX(RenderScript rs) {
+        if (rs.mElement_PROGRAM_VERTEX == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_VERTEX == null) {
+                    rs.mElement_PROGRAM_VERTEX = createUser(rs, DataType.RS_PROGRAM_VERTEX);
+                }
+            }
+        }
+        return rs.mElement_PROGRAM_VERTEX;
+    }
+
+    public static Element PROGRAM_RASTER(RenderScript rs) {
+        if (rs.mElement_PROGRAM_RASTER == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_RASTER == null) {
+                    rs.mElement_PROGRAM_RASTER = createUser(rs, DataType.RS_PROGRAM_RASTER);
+                }
+            }
+        }
+        return rs.mElement_PROGRAM_RASTER;
+    }
+
+    public static Element PROGRAM_STORE(RenderScript rs) {
+        if (rs.mElement_PROGRAM_STORE == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_STORE == null) {
+                    rs.mElement_PROGRAM_STORE = createUser(rs, DataType.RS_PROGRAM_STORE);
+                }
+            }
+        }
+        return rs.mElement_PROGRAM_STORE;
+    }
+
+    public static Element FONT(RenderScript rs) {
+        if (rs.mElement_FONT == null) {
+            synchronized (rs) {
+                if (rs.mElement_FONT == null) {
+                    rs.mElement_FONT = createUser(rs, DataType.RS_FONT);
+                }
+            }
+        }
+        return rs.mElement_FONT;
+    }
+
+    public static Element A_8(RenderScript rs) {
+        if (rs.mElement_A_8 == null) {
+            synchronized (rs) {
+                if (rs.mElement_A_8 == null) {
+                    rs.mElement_A_8 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_A);
+                }
+            }
+        }
+        return rs.mElement_A_8;
+    }
+
+    public static Element RGB_565(RenderScript rs) {
+        if (rs.mElement_RGB_565 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGB_565 == null) {
+                    rs.mElement_RGB_565 = createPixel(rs, DataType.UNSIGNED_5_6_5, DataKind.PIXEL_RGB);
+                }
+            }
+        }
+        return rs.mElement_RGB_565;
+    }
+
+    public static Element RGB_888(RenderScript rs) {
+        if (rs.mElement_RGB_888 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGB_888 == null) {
+                    rs.mElement_RGB_888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGB);
+                }
+            }
+        }
+        return rs.mElement_RGB_888;
+    }
+
+    public static Element RGBA_5551(RenderScript rs) {
+        if (rs.mElement_RGBA_5551 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGBA_5551 == null) {
+                    rs.mElement_RGBA_5551 = createPixel(rs, DataType.UNSIGNED_5_5_5_1, DataKind.PIXEL_RGBA);
+                }
+            }
+        }
+        return rs.mElement_RGBA_5551;
+    }
+
+    public static Element RGBA_4444(RenderScript rs) {
+        if (rs.mElement_RGBA_4444 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGBA_4444 == null) {
+                    rs.mElement_RGBA_4444 = createPixel(rs, DataType.UNSIGNED_4_4_4_4, DataKind.PIXEL_RGBA);
+                }
+            }
+        }
+        return rs.mElement_RGBA_4444;
+    }
+
+    public static Element RGBA_8888(RenderScript rs) {
+        if (rs.mElement_RGBA_8888 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGBA_8888 == null) {
+                    rs.mElement_RGBA_8888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGBA);
+                }
+            }
+        }
+        return rs.mElement_RGBA_8888;
+    }
+
+    public static Element F16_2(RenderScript rs) {
+        if (rs.mElement_HALF_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_HALF_2 == null) {
+                    rs.mElement_HALF_2 = createVector(rs, DataType.FLOAT_16, 2);
+                }
+            }
+        }
+        return rs.mElement_HALF_2;
+    }
+
+    public static Element F16_3(RenderScript rs) {
+        if (rs.mElement_HALF_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_HALF_3 == null) {
+                    rs.mElement_HALF_3 = createVector(rs, DataType.FLOAT_16, 3);
+                }
+            }
+        }
+        return rs.mElement_HALF_3;
+    }
+
+    public static Element F16_4(RenderScript rs) {
+        if (rs.mElement_HALF_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_HALF_4 == null) {
+                    rs.mElement_HALF_4 = createVector(rs, DataType.FLOAT_16, 4);
+                }
+            }
+        }
+        return rs.mElement_HALF_4;
+    }
+
+    public static Element F32_2(RenderScript rs) {
+        if (rs.mElement_FLOAT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_FLOAT_2 == null) {
+                    rs.mElement_FLOAT_2 = createVector(rs, DataType.FLOAT_32, 2);
+                }
+            }
+        }
+        return rs.mElement_FLOAT_2;
+    }
+
+    public static Element F32_3(RenderScript rs) {
+        if (rs.mElement_FLOAT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_FLOAT_3 == null) {
+                    rs.mElement_FLOAT_3 = createVector(rs, DataType.FLOAT_32, 3);
+                }
+            }
+        }
+        return rs.mElement_FLOAT_3;
+    }
+
+    public static Element F32_4(RenderScript rs) {
+        if (rs.mElement_FLOAT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_FLOAT_4 == null) {
+                    rs.mElement_FLOAT_4 = createVector(rs, DataType.FLOAT_32, 4);
+                }
+            }
+        }
+        return rs.mElement_FLOAT_4;
+    }
+
+    public static Element F64_2(RenderScript rs) {
+        if (rs.mElement_DOUBLE_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_DOUBLE_2 == null) {
+                    rs.mElement_DOUBLE_2 = createVector(rs, DataType.FLOAT_64, 2);
+                }
+            }
+        }
+        return rs.mElement_DOUBLE_2;
+    }
+
+    public static Element F64_3(RenderScript rs) {
+        if (rs.mElement_DOUBLE_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_DOUBLE_3 == null) {
+                    rs.mElement_DOUBLE_3 = createVector(rs, DataType.FLOAT_64, 3);
+                }
+            }
+        }
+        return rs.mElement_DOUBLE_3;
+    }
+
+    public static Element F64_4(RenderScript rs) {
+        if (rs.mElement_DOUBLE_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_DOUBLE_4 == null) {
+                    rs.mElement_DOUBLE_4 = createVector(rs, DataType.FLOAT_64, 4);
+                }
+            }
+        }
+        return rs.mElement_DOUBLE_4;
+    }
+
+    public static Element U8_2(RenderScript rs) {
+        if (rs.mElement_UCHAR_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UCHAR_2 == null) {
+                    rs.mElement_UCHAR_2 = createVector(rs, DataType.UNSIGNED_8, 2);
+                }
+            }
+        }
+        return rs.mElement_UCHAR_2;
+    }
+
+    public static Element U8_3(RenderScript rs) {
+        if (rs.mElement_UCHAR_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UCHAR_3 == null) {
+                    rs.mElement_UCHAR_3 = createVector(rs, DataType.UNSIGNED_8, 3);
+                }
+            }
+        }
+        return rs.mElement_UCHAR_3;
+    }
+
+    public static Element U8_4(RenderScript rs) {
+        if (rs.mElement_UCHAR_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UCHAR_4 == null) {
+                    rs.mElement_UCHAR_4 = createVector(rs, DataType.UNSIGNED_8, 4);
+                }
+            }
+        }
+        return rs.mElement_UCHAR_4;
+    }
+
+    public static Element I8_2(RenderScript rs) {
+        if (rs.mElement_CHAR_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_CHAR_2 == null) {
+                    rs.mElement_CHAR_2 = createVector(rs, DataType.SIGNED_8, 2);
+                }
+            }
+        }
+        return rs.mElement_CHAR_2;
+    }
+
+    public static Element I8_3(RenderScript rs) {
+        if (rs.mElement_CHAR_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_CHAR_3 == null) {
+                    rs.mElement_CHAR_3 = createVector(rs, DataType.SIGNED_8, 3);
+                }
+            }
+        }
+        return rs.mElement_CHAR_3;
+    }
+
+    public static Element I8_4(RenderScript rs) {
+        if (rs.mElement_CHAR_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_CHAR_4 == null) {
+                    rs.mElement_CHAR_4 = createVector(rs, DataType.SIGNED_8, 4);
+                }
+            }
+        }
+        return rs.mElement_CHAR_4;
+    }
+
+    public static Element U16_2(RenderScript rs) {
+        if (rs.mElement_USHORT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_USHORT_2 == null) {
+                    rs.mElement_USHORT_2 = createVector(rs, DataType.UNSIGNED_16, 2);
+                }
+            }
+        }
+        return rs.mElement_USHORT_2;
+    }
+
+    public static Element U16_3(RenderScript rs) {
+        if (rs.mElement_USHORT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_USHORT_3 == null) {
+                    rs.mElement_USHORT_3 = createVector(rs, DataType.UNSIGNED_16, 3);
+                }
+            }
+        }
+        return rs.mElement_USHORT_3;
+    }
+
+    public static Element U16_4(RenderScript rs) {
+        if (rs.mElement_USHORT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_USHORT_4 == null) {
+                    rs.mElement_USHORT_4 = createVector(rs, DataType.UNSIGNED_16, 4);
+                }
+            }
+        }
+        return rs.mElement_USHORT_4;
+    }
+
+    public static Element I16_2(RenderScript rs) {
+        if (rs.mElement_SHORT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_SHORT_2 == null) {
+                    rs.mElement_SHORT_2 = createVector(rs, DataType.SIGNED_16, 2);
+                }
+            }
+        }
+        return rs.mElement_SHORT_2;
+    }
+
+    public static Element I16_3(RenderScript rs) {
+        if (rs.mElement_SHORT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_SHORT_3 == null) {
+                    rs.mElement_SHORT_3 = createVector(rs, DataType.SIGNED_16, 3);
+                }
+            }
+        }
+        return rs.mElement_SHORT_3;
+    }
+
+    public static Element I16_4(RenderScript rs) {
+        if (rs.mElement_SHORT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_SHORT_4 == null) {
+                    rs.mElement_SHORT_4 = createVector(rs, DataType.SIGNED_16, 4);
+                }
+            }
+        }
+        return rs.mElement_SHORT_4;
+    }
+
+    public static Element U32_2(RenderScript rs) {
+        if (rs.mElement_UINT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UINT_2 == null) {
+                    rs.mElement_UINT_2 = createVector(rs, DataType.UNSIGNED_32, 2);
+                }
+            }
+        }
+        return rs.mElement_UINT_2;
+    }
+
+    public static Element U32_3(RenderScript rs) {
+        if (rs.mElement_UINT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UINT_3 == null) {
+                    rs.mElement_UINT_3 = createVector(rs, DataType.UNSIGNED_32, 3);
+                }
+            }
+        }
+        return rs.mElement_UINT_3;
+    }
+
+    public static Element U32_4(RenderScript rs) {
+        if (rs.mElement_UINT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UINT_4 == null) {
+                    rs.mElement_UINT_4 = createVector(rs, DataType.UNSIGNED_32, 4);
+                }
+            }
+        }
+        return rs.mElement_UINT_4;
+    }
+
+    public static Element I32_2(RenderScript rs) {
+        if (rs.mElement_INT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_INT_2 == null) {
+                    rs.mElement_INT_2 = createVector(rs, DataType.SIGNED_32, 2);
+                }
+            }
+        }
+        return rs.mElement_INT_2;
+    }
+
+    public static Element I32_3(RenderScript rs) {
+        if (rs.mElement_INT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_INT_3 == null) {
+                    rs.mElement_INT_3 = createVector(rs, DataType.SIGNED_32, 3);
+                }
+            }
+        }
+        return rs.mElement_INT_3;
+    }
+
+    public static Element I32_4(RenderScript rs) {
+        if (rs.mElement_INT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_INT_4 == null) {
+                    rs.mElement_INT_4 = createVector(rs, DataType.SIGNED_32, 4);
+                }
+            }
+        }
+        return rs.mElement_INT_4;
+    }
+
+    public static Element U64_2(RenderScript rs) {
+        if (rs.mElement_ULONG_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_ULONG_2 == null) {
+                    rs.mElement_ULONG_2 = createVector(rs, DataType.UNSIGNED_64, 2);
+                }
+            }
+        }
+        return rs.mElement_ULONG_2;
+    }
+
+    public static Element U64_3(RenderScript rs) {
+        if (rs.mElement_ULONG_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_ULONG_3 == null) {
+                    rs.mElement_ULONG_3 = createVector(rs, DataType.UNSIGNED_64, 3);
+                }
+            }
+        }
+        return rs.mElement_ULONG_3;
+    }
+
+    public static Element U64_4(RenderScript rs) {
+        if (rs.mElement_ULONG_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_ULONG_4 == null) {
+                    rs.mElement_ULONG_4 = createVector(rs, DataType.UNSIGNED_64, 4);
+                }
+            }
+        }
+        return rs.mElement_ULONG_4;
+    }
+
+    public static Element I64_2(RenderScript rs) {
+        if (rs.mElement_LONG_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_LONG_2 == null) {
+                    rs.mElement_LONG_2 = createVector(rs, DataType.SIGNED_64, 2);
+                }
+            }
+        }
+        return rs.mElement_LONG_2;
+    }
+
+    public static Element I64_3(RenderScript rs) {
+        if (rs.mElement_LONG_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_LONG_3 == null) {
+                    rs.mElement_LONG_3 = createVector(rs, DataType.SIGNED_64, 3);
+                }
+            }
+        }
+        return rs.mElement_LONG_3;
+    }
+
+    public static Element I64_4(RenderScript rs) {
+        if (rs.mElement_LONG_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_LONG_4 == null) {
+                    rs.mElement_LONG_4 = createVector(rs, DataType.SIGNED_64, 4);
+                }
+            }
+        }
+        return rs.mElement_LONG_4;
+    }
+
+    public static Element YUV(RenderScript rs) {
+        if (rs.mElement_YUV == null) {
+            synchronized (rs) {
+                if (rs.mElement_YUV == null) {
+                    rs.mElement_YUV = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_YUV);
+                }
+            }
+        }
+        return rs.mElement_YUV;
+    }
+
+    public static Element MATRIX_4X4(RenderScript rs) {
+        if (rs.mElement_MATRIX_4X4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_MATRIX_4X4 == null) {
+                    rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
+                }
+            }
+        }
+        return rs.mElement_MATRIX_4X4;
+    }
+
+    /** @deprecated use MATRIX_4X4
+    */
+    public static Element MATRIX4X4(RenderScript rs) {
+        return MATRIX_4X4(rs);
+    }
+
+    public static Element MATRIX_3X3(RenderScript rs) {
+        if (rs.mElement_MATRIX_3X3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_MATRIX_3X3 == null) {
+                    rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3);
+                }
+            }
+        }
+        return rs.mElement_MATRIX_3X3;
+    }
+
+    public static Element MATRIX_2X2(RenderScript rs) {
+        if (rs.mElement_MATRIX_2X2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_MATRIX_2X2 == null) {
+                    rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2);
+                }
+            }
+        }
+        return rs.mElement_MATRIX_2X2;
+    }
+
+    Element(long id, RenderScript rs, Element[] e, String[] n, int[] as) {
+        super(id, rs);
+        mSize = 0;
+        mVectorSize = 1;
+        mElements = e;
+        mElementNames = n;
+        mArraySizes = as;
+        mType = DataType.NONE;
+        mKind = DataKind.USER;
+        mOffsetInBytes = new int[mElements.length];
+        for (int ct = 0; ct < mElements.length; ct++ ) {
+            mOffsetInBytes[ct] = mSize;
+            mSize += mElements[ct].mSize * mArraySizes[ct];
+        }
+        updateVisibleSubElements();
+    }
+
+    Element(long id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
+        super(id, rs);
+        if ((dt != DataType.UNSIGNED_5_6_5) &&
+            (dt != DataType.UNSIGNED_4_4_4_4) &&
+            (dt != DataType.UNSIGNED_5_5_5_1)) {
+            if (size == 3) {
+                mSize = dt.mSize * 4;
+            } else {
+                mSize = dt.mSize * size;
+            }
+        } else {
+            mSize = dt.mSize;
+        }
+        mType = dt;
+        mKind = dk;
+        mNormalized = norm;
+        mVectorSize = size;
+    }
+
+    Element(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    @Override
+    void updateFromNative() {
+        super.updateFromNative();
+
+        // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
+        int[] dataBuffer = new int[5];
+        mRS.nElementGetNativeData(getID(mRS), dataBuffer);
+
+        mNormalized = dataBuffer[2] == 1 ? true : false;
+        mVectorSize = dataBuffer[3];
+        mSize = 0;
+        for (DataType dt: DataType.values()) {
+            if(dt.mID == dataBuffer[0]){
+                mType = dt;
+                mSize = mType.mSize * mVectorSize;
+            }
+        }
+        for (DataKind dk: DataKind.values()) {
+            if(dk.mID == dataBuffer[1]){
+                mKind = dk;
+            }
+        }
+
+        int numSubElements = dataBuffer[4];
+        if(numSubElements > 0) {
+            mElements = new Element[numSubElements];
+            mElementNames = new String[numSubElements];
+            mArraySizes = new int[numSubElements];
+            mOffsetInBytes = new int[numSubElements];
+
+            long[] subElementIds = new long[numSubElements];
+            mRS.nElementGetSubElements(getID(mRS), subElementIds, mElementNames, mArraySizes);
+            for(int i = 0; i < numSubElements; i ++) {
+                mElements[i] = new Element(subElementIds[i], mRS);
+                mElements[i].updateFromNative();
+                mOffsetInBytes[i] = mSize;
+                mSize += mElements[i].mSize * mArraySizes[i];
+            }
+        }
+        updateVisibleSubElements();
+    }
+
+    /**
+     * Create a custom Element of the specified DataType.  The DataKind will be
+     * set to USER and the vector size to 1 indicating non-vector.
+     *
+     * @param rs The context associated with the new Element.
+     * @param dt The DataType for the new element.
+     * @return Element
+     */
+    @UnsupportedAppUsage
+    static Element createUser(RenderScript rs, DataType dt) {
+        DataKind dk = DataKind.USER;
+        boolean norm = false;
+        int vecSize = 1;
+        long id = rs.nElementCreate(dt.mID, dk.mID, norm, vecSize);
+        return new Element(id, rs, dt, dk, norm, vecSize);
+    }
+
+    /**
+     * Create a custom vector element of the specified DataType and vector size.
+     * DataKind will be set to USER. Only primitive types (FLOAT_32, FLOAT_64,
+     * SIGNED_8, SIGNED_16, SIGNED_32, SIGNED_64, UNSIGNED_8, UNSIGNED_16,
+     * UNSIGNED_32, UNSIGNED_64, BOOLEAN) are supported.
+     *
+     * @param rs The context associated with the new Element.
+     * @param dt The DataType for the new Element.
+     * @param size Vector size for the new Element.  Range 2-4 inclusive
+     *             supported.
+     *
+     * @return Element
+     */
+    public static Element createVector(RenderScript rs, DataType dt, int size) {
+        if (size < 2 || size > 4) {
+            throw new RSIllegalArgumentException("Vector size out of range 2-4.");
+        }
+
+        switch (dt) {
+        // Support only primitive integer/float/boolean types as vectors.
+        case FLOAT_16:
+        case FLOAT_32:
+        case FLOAT_64:
+        case SIGNED_8:
+        case SIGNED_16:
+        case SIGNED_32:
+        case SIGNED_64:
+        case UNSIGNED_8:
+        case UNSIGNED_16:
+        case UNSIGNED_32:
+        case UNSIGNED_64:
+        case BOOLEAN: {
+            DataKind dk = DataKind.USER;
+            boolean norm = false;
+            long id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
+            return new Element(id, rs, dt, dk, norm, size);
+        }
+
+        default: {
+            throw new RSIllegalArgumentException("Cannot create vector of " +
+                "non-primitive type.");
+        }
+        }
+    }
+
+    /**
+     * Create a new pixel Element type.  A matching DataType and DataKind must
+     * be provided.  The DataType and DataKind must contain the same number of
+     * components.  Vector size will be set to 1.
+     *
+     * @param rs The context associated with the new Element.
+     * @param dt The DataType for the new element.
+     * @param dk The DataKind to specify the mapping of each component in the
+     *           DataType.
+     *
+     * @return Element
+     */
+    public static Element createPixel(RenderScript rs, DataType dt, DataKind dk) {
+        if (!(dk == DataKind.PIXEL_L ||
+              dk == DataKind.PIXEL_A ||
+              dk == DataKind.PIXEL_LA ||
+              dk == DataKind.PIXEL_RGB ||
+              dk == DataKind.PIXEL_RGBA ||
+              dk == DataKind.PIXEL_DEPTH ||
+              dk == DataKind.PIXEL_YUV)) {
+            throw new RSIllegalArgumentException("Unsupported DataKind");
+        }
+        if (!(dt == DataType.UNSIGNED_8 ||
+              dt == DataType.UNSIGNED_16 ||
+              dt == DataType.UNSIGNED_5_6_5 ||
+              dt == DataType.UNSIGNED_4_4_4_4 ||
+              dt == DataType.UNSIGNED_5_5_5_1)) {
+            throw new RSIllegalArgumentException("Unsupported DataType");
+        }
+        if (dt == DataType.UNSIGNED_5_6_5 && dk != DataKind.PIXEL_RGB) {
+            throw new RSIllegalArgumentException("Bad kind and type combo");
+        }
+        if (dt == DataType.UNSIGNED_5_5_5_1 && dk != DataKind.PIXEL_RGBA) {
+            throw new RSIllegalArgumentException("Bad kind and type combo");
+        }
+        if (dt == DataType.UNSIGNED_4_4_4_4 && dk != DataKind.PIXEL_RGBA) {
+            throw new RSIllegalArgumentException("Bad kind and type combo");
+        }
+        if (dt == DataType.UNSIGNED_16 &&
+            dk != DataKind.PIXEL_DEPTH) {
+            throw new RSIllegalArgumentException("Bad kind and type combo");
+        }
+
+        int size = 1;
+        switch (dk) {
+        case PIXEL_LA:
+            size = 2;
+            break;
+        case PIXEL_RGB:
+            size = 3;
+            break;
+        case PIXEL_RGBA:
+            size = 4;
+            break;
+        case PIXEL_DEPTH:
+            size = 2;
+            break;
+        }
+
+        boolean norm = true;
+        long id = rs.nElementCreate(dt.mID, dk.mID, norm, size);
+        return new Element(id, rs, dt, dk, norm, size);
+    }
+
+    /**
+     * Check if the current Element is compatible with another Element.
+     * Primitive Elements are compatible if they share the same underlying
+     * size and type (i.e. U8 is compatible with A_8). User-defined Elements
+     * must be equal in order to be compatible. This requires strict name
+     * equivalence for all sub-Elements (in addition to structural equivalence).
+     *
+     * @param e The Element to check compatibility with.
+     *
+     * @return boolean true if the Elements are compatible, otherwise false.
+     */
+    public boolean isCompatible(Element e) {
+        // Try strict BaseObj equality to start with.
+        if (this.equals(e)) {
+            return true;
+        }
+
+        // Ignore mKind because it is allowed to be different (user vs. pixel).
+        // We also ignore mNormalized because it can be different. The mType
+        // field must not be NONE since we require name equivalence for
+        // all user-created Elements.
+        return ((mSize == e.mSize) &&
+                (mType != DataType.NONE) &&
+                (mType == e.mType) &&
+                (mVectorSize == e.mVectorSize));
+    }
+
+    /**
+     * Builder class for producing complex elements with matching field and name
+     * pairs.  The builder starts empty.  The order in which elements are added
+     * is retained for the layout in memory.
+     *
+     */
+    public static class Builder {
+        RenderScript mRS;
+        Element[] mElements;
+        String[] mElementNames;
+        int[] mArraySizes;
+        int mCount;
+        int mSkipPadding;
+
+        /**
+         * Create a builder object.
+         *
+         * @param rs
+         */
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mCount = 0;
+            mElements = new Element[8];
+            mElementNames = new String[8];
+            mArraySizes = new int[8];
+        }
+
+        /**
+         * Add an array of elements to this element.
+         *
+         * @param element
+         * @param name
+         * @param arraySize
+         */
+        public Builder add(Element element, String name, int arraySize) {
+            if (arraySize < 1) {
+                throw new RSIllegalArgumentException("Array size cannot be less than 1.");
+            }
+
+            // Skip padding fields after a vector 3 type.
+            if (mSkipPadding != 0) {
+                if (name.startsWith("#padding_")) {
+                    mSkipPadding = 0;
+                    return this;
+                }
+            }
+
+            if (element.mVectorSize == 3) {
+                mSkipPadding = 1;
+            } else {
+                mSkipPadding = 0;
+            }
+
+            if(mCount == mElements.length) {
+                Element[] e = new Element[mCount + 8];
+                String[] s = new String[mCount + 8];
+                int[] as = new int[mCount + 8];
+                System.arraycopy(mElements, 0, e, 0, mCount);
+                System.arraycopy(mElementNames, 0, s, 0, mCount);
+                System.arraycopy(mArraySizes, 0, as, 0, mCount);
+                mElements = e;
+                mElementNames = s;
+                mArraySizes = as;
+            }
+            mElements[mCount] = element;
+            mElementNames[mCount] = name;
+            mArraySizes[mCount] = arraySize;
+            mCount++;
+            return this;
+        }
+
+        /**
+         * Add a single element to this Element.
+         *
+         * @param element
+         * @param name
+         */
+        public Builder add(Element element, String name) {
+            return add(element, name, 1);
+        }
+
+        /**
+         * Create the element from this builder.
+         *
+         *
+         * @return Element
+         */
+        public Element create() {
+            mRS.validate();
+            Element[] ein = new Element[mCount];
+            String[] sin = new String[mCount];
+            int[] asin = new int[mCount];
+            java.lang.System.arraycopy(mElements, 0, ein, 0, mCount);
+            java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount);
+            java.lang.System.arraycopy(mArraySizes, 0, asin, 0, mCount);
+
+            long[] ids = new long[ein.length];
+            for (int ct = 0; ct < ein.length; ct++ ) {
+                ids[ct] = ein[ct].getID(mRS);
+            }
+            long id = mRS.nElementCreate2(ids, sin, asin);
+            return new Element(id, mRS, ein, sin, asin);
+        }
+    }
+}
+
diff --git a/android/renderscript/FieldPacker.java b/android/renderscript/FieldPacker.java
new file mode 100644
index 0000000..aaa0fe8
--- /dev/null
+++ b/android/renderscript/FieldPacker.java
@@ -0,0 +1,812 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import java.util.BitSet;
+
+/**
+ * Utility class for packing arguments and structures from Android system objects to
+ * RenderScript objects.
+ *
+ * This class is only intended to be used to support the
+ * reflected code generated by the RS tool chain.  It should not
+ * be called directly.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class FieldPacker {
+    public FieldPacker(int len) {
+        mPos = 0;
+        mLen = len;
+        mData = new byte[len];
+        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.
+    }
+
+    static FieldPacker createFromArray(Object[] args) {
+        FieldPacker fp = new FieldPacker(RenderScript.sPointerSize * 8);
+        for (Object arg : args) {
+            fp.addSafely(arg);
+        }
+        fp.resize(fp.mPos);
+        return fp;
+    }
+
+    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);
+        }
+
+        while ((mPos & (v - 1)) != 0) {
+            mAlignment.flip(mPos);
+            mData[mPos++] = 0;
+        }
+    }
+
+    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)) {
+            throw new RSIllegalArgumentException("out of range argument: " + i);
+        }
+        mPos = i;
+    }
+
+    public void skip(int i) {
+        int res = mPos + i;
+        if ((res < 0) || (res > mLen)) {
+            throw new RSIllegalArgumentException("out of range argument: " + i);
+        }
+        mPos = res;
+    }
+
+    public void addI8(byte v) {
+        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);
+        mData[mPos++] = (byte)((v >> 8) & 0xff);
+        mData[mPos++] = (byte)((v >> 16) & 0xff);
+        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);
+        mData[mPos++] = (byte)((v >> 8) & 0xff);
+        mData[mPos++] = (byte)((v >> 16) & 0xff);
+        mData[mPos++] = (byte)((v >> 24) & 0xff);
+        mData[mPos++] = (byte)((v >> 32) & 0xff);
+        mData[mPos++] = (byte)((v >> 40) & 0xff);
+        mData[mPos++] = (byte)((v >> 48) & 0xff);
+        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;
+    }
+
+    public void addU16(int v) {
+        if ((v < 0) || (v > 0xffff)) {
+            android.util.Log.e("rs", "FieldPacker.addU16( " + v + " )");
+            throw new IllegalArgumentException("Saving value out of range for type");
+        }
+        align(2);
+        mData[mPos++] = (byte)(v & 0xff);
+        mData[mPos++] = (byte)(v >> 8);
+    }
+
+    public void addU32(long v) {
+        if ((v < 0) || (v > 0xffffffffL)) {
+            android.util.Log.e("rs", "FieldPacker.addU32( " + v + " )");
+            throw new IllegalArgumentException("Saving value out of range for type");
+        }
+        align(4);
+        mData[mPos++] = (byte)(v & 0xff);
+        mData[mPos++] = (byte)((v >> 8) & 0xff);
+        mData[mPos++] = (byte)((v >> 16) & 0xff);
+        mData[mPos++] = (byte)((v >> 24) & 0xff);
+    }
+
+    public void addU64(long v) {
+        if (v < 0) {
+            android.util.Log.e("rs", "FieldPacker.addU64( " + v + " )");
+            throw new IllegalArgumentException("Saving value out of range for type");
+        }
+        align(8);
+        mData[mPos++] = (byte)(v & 0xff);
+        mData[mPos++] = (byte)((v >> 8) & 0xff);
+        mData[mPos++] = (byte)((v >> 16) & 0xff);
+        mData[mPos++] = (byte)((v >> 24) & 0xff);
+        mData[mPos++] = (byte)((v >> 32) & 0xff);
+        mData[mPos++] = (byte)((v >> 40) & 0xff);
+        mData[mPos++] = (byte)((v >> 48) & 0xff);
+        mData[mPos++] = (byte)((v >> 56) & 0xff);
+    }
+
+    public void addF32(float v) {
+        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) {
+                addI64(obj.getID(null));
+                addI64(0);
+                addI64(0);
+                addI64(0);
+            } else {
+                addI32((int)obj.getID(null));
+            }
+        } else {
+            if (RenderScript.sPointerSize == 8) {
+                addI64(0);
+                addI64(0);
+                addI64(0);
+                addI64(0);
+            } else {
+                addI32(0);
+            }
+        }
+    }
+
+    public void addF32(Float2 v) {
+        addF32(v.x);
+        addF32(v.y);
+    }
+    public void addF32(Float3 v) {
+        addF32(v.x);
+        addF32(v.y);
+        addF32(v.z);
+    }
+    public void addF32(Float4 v) {
+        addF32(v.x);
+        addF32(v.y);
+        addF32(v.z);
+        addF32(v.w);
+    }
+
+    public void addF64(Double2 v) {
+        addF64(v.x);
+        addF64(v.y);
+    }
+    public void addF64(Double3 v) {
+        addF64(v.x);
+        addF64(v.y);
+        addF64(v.z);
+    }
+    public void addF64(Double4 v) {
+        addF64(v.x);
+        addF64(v.y);
+        addF64(v.z);
+        addF64(v.w);
+    }
+
+    public void addI8(Byte2 v) {
+        addI8(v.x);
+        addI8(v.y);
+    }
+    public void addI8(Byte3 v) {
+        addI8(v.x);
+        addI8(v.y);
+        addI8(v.z);
+    }
+    public void addI8(Byte4 v) {
+        addI8(v.x);
+        addI8(v.y);
+        addI8(v.z);
+        addI8(v.w);
+    }
+
+    public void addU8(Short2 v) {
+        addU8(v.x);
+        addU8(v.y);
+    }
+    public void addU8(Short3 v) {
+        addU8(v.x);
+        addU8(v.y);
+        addU8(v.z);
+    }
+    public void addU8(Short4 v) {
+        addU8(v.x);
+        addU8(v.y);
+        addU8(v.z);
+        addU8(v.w);
+    }
+
+    public void addI16(Short2 v) {
+        addI16(v.x);
+        addI16(v.y);
+    }
+    public void addI16(Short3 v) {
+        addI16(v.x);
+        addI16(v.y);
+        addI16(v.z);
+    }
+    public void addI16(Short4 v) {
+        addI16(v.x);
+        addI16(v.y);
+        addI16(v.z);
+        addI16(v.w);
+    }
+
+    public void addU16(Int2 v) {
+        addU16(v.x);
+        addU16(v.y);
+    }
+    public void addU16(Int3 v) {
+        addU16(v.x);
+        addU16(v.y);
+        addU16(v.z);
+    }
+    public void addU16(Int4 v) {
+        addU16(v.x);
+        addU16(v.y);
+        addU16(v.z);
+        addU16(v.w);
+    }
+
+    public void addI32(Int2 v) {
+        addI32(v.x);
+        addI32(v.y);
+    }
+    public void addI32(Int3 v) {
+        addI32(v.x);
+        addI32(v.y);
+        addI32(v.z);
+    }
+    public void addI32(Int4 v) {
+        addI32(v.x);
+        addI32(v.y);
+        addI32(v.z);
+        addI32(v.w);
+    }
+
+    public void addU32(Long2 v) {
+        addU32(v.x);
+        addU32(v.y);
+    }
+    public void addU32(Long3 v) {
+        addU32(v.x);
+        addU32(v.y);
+        addU32(v.z);
+    }
+    public void addU32(Long4 v) {
+        addU32(v.x);
+        addU32(v.y);
+        addU32(v.z);
+        addU32(v.w);
+    }
+
+    public void addI64(Long2 v) {
+        addI64(v.x);
+        addI64(v.y);
+    }
+    public void addI64(Long3 v) {
+        addI64(v.x);
+        addI64(v.y);
+        addI64(v.z);
+    }
+    public void addI64(Long4 v) {
+        addI64(v.x);
+        addI64(v.y);
+        addI64(v.z);
+        addI64(v.w);
+    }
+
+    public void addU64(Long2 v) {
+        addU64(v.x);
+        addU64(v.y);
+    }
+    public void addU64(Long3 v) {
+        addU64(v.x);
+        addU64(v.y);
+        addU64(v.z);
+    }
+    public void addU64(Long4 v) {
+        addU64(v.x);
+        addU64(v.y);
+        addU64(v.z);
+        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 void add(Object obj) {
+        if (obj instanceof Boolean) {
+            addBoolean((Boolean)obj);
+            return;
+        }
+
+        if (obj instanceof Byte) {
+            addI8((Byte)obj);
+            return;
+        }
+
+        if (obj instanceof Short) {
+            addI16((Short)obj);
+            return;
+        }
+
+        if (obj instanceof Integer) {
+            addI32((Integer)obj);
+            return;
+        }
+
+        if (obj instanceof Long) {
+            addI64((Long)obj);
+            return;
+        }
+
+        if (obj instanceof Float) {
+            addF32((Float)obj);
+            return;
+        }
+
+        if (obj instanceof Double) {
+            addF64((Double)obj);
+            return;
+        }
+
+        if (obj instanceof Byte2) {
+            addI8((Byte2)obj);
+            return;
+        }
+
+        if (obj instanceof Byte3) {
+            addI8((Byte3)obj);
+            return;
+        }
+
+        if (obj instanceof Byte4) {
+            addI8((Byte4)obj);
+            return;
+        }
+
+        if (obj instanceof Short2) {
+            addI16((Short2)obj);
+            return;
+        }
+
+        if (obj instanceof Short3) {
+            addI16((Short3)obj);
+            return;
+        }
+
+        if (obj instanceof Short4) {
+            addI16((Short4)obj);
+            return;
+        }
+
+        if (obj instanceof Int2) {
+            addI32((Int2)obj);
+            return;
+        }
+
+        if (obj instanceof Int3) {
+            addI32((Int3)obj);
+            return;
+        }
+
+        if (obj instanceof Int4) {
+            addI32((Int4)obj);
+            return;
+        }
+
+        if (obj instanceof Long2) {
+            addI64((Long2)obj);
+            return;
+        }
+
+        if (obj instanceof Long3) {
+            addI64((Long3)obj);
+            return;
+        }
+
+        if (obj instanceof Long4) {
+            addI64((Long4)obj);
+            return;
+        }
+
+        if (obj instanceof Float2) {
+            addF32((Float2)obj);
+            return;
+        }
+
+        if (obj instanceof Float3) {
+            addF32((Float3)obj);
+            return;
+        }
+
+        if (obj instanceof Float4) {
+            addF32((Float4)obj);
+            return;
+        }
+
+        if (obj instanceof Double2) {
+            addF64((Double2)obj);
+            return;
+        }
+
+        if (obj instanceof Double3) {
+            addF64((Double3)obj);
+            return;
+        }
+
+        if (obj instanceof Double4) {
+            addF64((Double4)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix2f) {
+            addMatrix((Matrix2f)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix3f) {
+            addMatrix((Matrix3f)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix4f) {
+            addMatrix((Matrix4f)obj);
+            return;
+        }
+
+        if (obj instanceof BaseObj) {
+            addObj((BaseObj)obj);
+            return;
+        }
+    }
+
+    private boolean resize(int newSize) {
+        if (newSize == mLen) {
+            return false;
+        }
+
+        byte[] newData = new byte[newSize];
+        System.arraycopy(mData, 0, newData, 0, mPos);
+        mData = newData;
+        mLen = newSize;
+        return true;
+    }
+
+    private void addSafely(Object obj) {
+        boolean retry;
+        final int oldPos = mPos;
+        do {
+            retry = false;
+            try {
+                add(obj);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                mPos = oldPos;
+                resize(mLen * 2);
+                retry = true;
+            }
+        } while (retry);
+    }
+
+    private byte mData[];
+    private int mPos;
+    private int mLen;
+    private BitSet mAlignment;
+}
diff --git a/android/renderscript/FileA3D.java b/android/renderscript/FileA3D.java
new file mode 100644
index 0000000..f0a9fa7
--- /dev/null
+++ b/android/renderscript/FileA3D.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+
+import java.io.File;
+import java.io.InputStream;
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * FileA3D allows users to load RenderScript objects from files
+ * or resources stored on disk. It could be used to load items
+ * such as 3D geometry data converted to a RenderScript format from
+ * content creation tools. Currently only meshes are supported
+ * in FileA3D.
+ *
+ * When successfully loaded, FileA3D will contain a list of
+ * index entries for all the objects stored inside it.
+ *
+ **/
+@Deprecated
+public class FileA3D extends BaseObj {
+
+    /**
+    * @deprecated in API 16
+    * Specifies what renderscript object type is contained within
+    * the FileA3D IndexEntry
+    **/
+    public enum EntryType {
+
+        /**
+        * @deprecated in API 16
+        * Unknown or or invalid object, nothing will be loaded
+        **/
+        UNKNOWN (0),
+        /**
+        * @deprecated in API 16
+        * RenderScript Mesh object
+        **/
+        @UnsupportedAppUsage
+        MESH (1);
+
+        int mID;
+        EntryType(int id) {
+            mID = id;
+        }
+
+        static EntryType toEntryType(int intID) {
+            return EntryType.values()[intID];
+        }
+    }
+
+    /**
+    * @deprecated in API 16
+    * IndexEntry contains information about one of the RenderScript
+    * objects inside the file's index. It could be used to query the
+    * object's type and also name and load the object itself if
+    * necessary.
+    */
+    public static class IndexEntry {
+        RenderScript mRS;
+        int mIndex;
+        long mID;
+        String mName;
+        EntryType mEntryType;
+        BaseObj mLoadedObj;
+
+        /**
+        * @deprecated in API 16
+        * Returns the name of a renderscript object the index entry
+        * describes
+        *
+        * @return name of a renderscript object the index entry
+        * describes
+        *
+        */
+        public String getName() {
+            return mName;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Returns the type of a renderscript object the index entry
+        * describes
+        * @return type of a renderscript object the index entry
+        *         describes
+        */
+        @UnsupportedAppUsage
+        public EntryType getEntryType() {
+            return mEntryType;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Used to load the object described by the index entry
+        * @return base renderscript object described by the entry
+        */
+        @UnsupportedAppUsage
+        public BaseObj getObject() {
+            mRS.validate();
+            BaseObj obj = internalCreate(mRS, this);
+            return obj;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Used to load the mesh described by the index entry, object
+        * described by the index entry must be a renderscript mesh
+        *
+        * @return renderscript mesh object described by the entry
+        */
+        public Mesh getMesh() {
+            return (Mesh)getObject();
+        }
+
+        static synchronized BaseObj internalCreate(RenderScript rs, IndexEntry entry) {
+            if(entry.mLoadedObj != null) {
+                return entry.mLoadedObj;
+            }
+
+            // to be purged on cleanup
+            if(entry.mEntryType == EntryType.UNKNOWN) {
+                return null;
+            }
+
+            long objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
+            if(objectID == 0) {
+                return null;
+            }
+
+            switch (entry.mEntryType) {
+            case MESH:
+                entry.mLoadedObj = new Mesh(objectID, rs);
+                break;
+
+            default:
+                throw new RSRuntimeException("Unrecognized object type in file.");
+            }
+
+            entry.mLoadedObj.updateFromNative();
+            return entry.mLoadedObj;
+        }
+
+        IndexEntry(RenderScript rs, int index, long id, String name, EntryType type) {
+            mRS = rs;
+            mIndex = index;
+            mID = id;
+            mName = name;
+            mEntryType = type;
+            mLoadedObj = null;
+        }
+    }
+
+    IndexEntry[] mFileEntries;
+    InputStream mInputStream;
+
+    FileA3D(long id, RenderScript rs, InputStream stream) {
+        super(id, rs);
+        mInputStream = stream;
+        guard.open("destroy");
+    }
+
+    private void initEntries() {
+        int numFileEntries = mRS.nFileA3DGetNumIndexEntries(getID(mRS));
+        if(numFileEntries <= 0) {
+            return;
+        }
+
+        mFileEntries = new IndexEntry[numFileEntries];
+        int[] ids = new int[numFileEntries];
+        String[] names = new String[numFileEntries];
+
+        mRS.nFileA3DGetIndexEntries(getID(mRS), numFileEntries, ids, names);
+
+        for(int i = 0; i < numFileEntries; i ++) {
+            mFileEntries[i] = new IndexEntry(mRS, i, getID(mRS), names[i], EntryType.toEntryType(ids[i]));
+        }
+    }
+
+    /**
+    * @deprecated in API 16
+    * Returns the number of objects stored inside the a3d file
+    *
+    * @return the number of objects stored inside the a3d file
+    */
+    public int getIndexEntryCount() {
+        if(mFileEntries == null) {
+            return 0;
+        }
+        return mFileEntries.length;
+    }
+
+    /**
+    * @deprecated in API 16
+    * Returns an index entry from the list of all objects inside
+    * FileA3D
+    *
+    * @param index number of the entry from the list to return
+    *
+    * @return entry in the a3d file described by the index
+    */
+    @UnsupportedAppUsage
+    public IndexEntry getIndexEntry(int index) {
+        if(getIndexEntryCount() == 0 || index < 0 || index >= mFileEntries.length) {
+            return null;
+        }
+        return mFileEntries[index];
+    }
+
+    /**
+    * @deprecated in API 16
+    * Creates a FileA3D object from an asset stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param mgr asset manager used to load asset
+    * @param path location of the file to load
+    *
+    * @return a3d file containing renderscript objects
+    */
+    static public FileA3D createFromAsset(RenderScript rs, AssetManager mgr, String path) {
+        rs.validate();
+        long fileId = rs.nFileA3DCreateFromAsset(mgr, path);
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from asset " + path);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, null);
+        fa3d.initEntries();
+        return fa3d;
+    }
+
+    /**
+    * @deprecated in API 16
+    * Creates a FileA3D object from a file stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param path location of the file to load
+    *
+    * @return a3d file containing renderscript objects
+    */
+    static public FileA3D createFromFile(RenderScript rs, String path) {
+        long fileId = rs.nFileA3DCreateFromFile(path);
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from " + path);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, null);
+        fa3d.initEntries();
+        return fa3d;
+    }
+
+    /**
+    * @deprecated in API 16
+    * Creates a FileA3D object from a file stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param path location of the file to load
+    *
+    * @return a3d file containing renderscript objects
+    */
+    static public FileA3D createFromFile(RenderScript rs, File path) {
+        return createFromFile(rs, path.getAbsolutePath());
+    }
+
+    /**
+    * @deprecated in API 16
+    * Creates a FileA3D object from an application resource
+    *
+    * @param rs Context to which the object will belong.
+    * @param res resource manager used for loading
+    * @param id resource to create FileA3D from
+    *
+    * @return a3d file containing renderscript objects
+    */
+    @UnsupportedAppUsage
+    static public FileA3D createFromResource(RenderScript rs, Resources res, int id) {
+
+        rs.validate();
+        InputStream is = null;
+        try {
+            is = res.openRawResource(id);
+        } catch (Exception e) {
+            throw new RSRuntimeException("Unable to open resource " + id);
+        }
+
+        long fileId = 0;
+        if (is instanceof AssetManager.AssetInputStream) {
+            long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
+            fileId = rs.nFileA3DCreateFromAssetStream(asset);
+        } else {
+            throw new RSRuntimeException("Unsupported asset stream");
+        }
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from resource " + id);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, is);
+        fa3d.initEntries();
+        return fa3d;
+
+    }
+}
diff --git a/android/renderscript/Float2.java b/android/renderscript/Float2.java
new file mode 100644
index 0000000..1f6038c
--- /dev/null
+++ b/android/renderscript/Float2.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic float type.
+ * Provides two float fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public  class Float2 {
+    public float x;
+    public float y;
+
+    public Float2() {
+    }
+    /** @hide */
+    public Float2(Float2 data) {
+        this.x = data.x;
+        this.y = data.y;
+    }
+
+    public Float2(float x, float y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 add(Float2 a, Float2 b) {
+        Float2 res = new Float2();
+        res.x = a.x + b.x;
+        res.y = a.y + b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(Float2 value) {
+        x += value.x;
+        y += value.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(float value) {
+        x += value;
+        y += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 add(Float2 a, float b) {
+        Float2 res = new Float2();
+        res.x = a.x + b;
+        res.y = a.y + b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(Float2 value) {
+        x -= value.x;
+        y -= value.y;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 sub(Float2 a, Float2 b) {
+        Float2 res = new Float2();
+        res.x = a.x - b.x;
+        res.y = a.y - b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(float value) {
+        x -= value;
+        y -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 sub(Float2 a, float b) {
+        Float2 res = new Float2();
+        res.x = a.x - b;
+        res.y = a.y - b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(Float2 value) {
+        x *= value.x;
+        y *= value.y;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 mul(Float2 a, Float2 b) {
+        Float2 res = new Float2();
+        res.x = a.x * b.x;
+        res.y = a.y * b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(float value) {
+        x *= value;
+        y *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 mul(Float2 a, float b) {
+        Float2 res = new Float2();
+        res.x = a.x * b;
+        res.y = a.y * b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(Float2 value) {
+        x /= value.x;
+        y /= value.y;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 div(Float2 a, Float2 b) {
+        Float2 res = new Float2();
+        res.x = a.x / b.x;
+        res.y = a.y / b.y;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(float value) {
+        x /= value;
+        y /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float2 div(Float2 a, float b) {
+        Float2 res = new Float2();
+        res.x = a.x / b;
+        res.y = a.y / b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public float dotProduct(Float2 a) {
+        return (x * a.x) + (y * a.y);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static float dotProduct(Float2 a, Float2 b) {
+        return (b.x * a.x) + (b.y * a.y);
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Float2 a, float factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+    }
+
+    /** @hide
+     * set vector value by float2
+     *
+     * @param a
+     */
+    public void set(Float2 a) {
+        this.x = a.x;
+        this.y = a.y;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        x = -x;
+        y = -y;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 2;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public float elementSum() {
+        return x + y;
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public float get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, float value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, float value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value
+     *
+     * @param x
+     * @param y
+     */
+    public void setValues(float x, float y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide
+     * copy the vector to float array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(float[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+    }
+}
diff --git a/android/renderscript/Float3.java b/android/renderscript/Float3.java
new file mode 100644
index 0000000..5f45716
--- /dev/null
+++ b/android/renderscript/Float3.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic float type.
+ * Provides three float fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Float3 {
+    public float x;
+    public float y;
+    public float z;
+
+    public Float3() {
+    }
+    /** @hide */
+    public Float3(Float3 data) {
+        this.x = data.x;
+        this.y = data.y;
+        this.z = data.z;
+    }
+
+    public Float3(float x, float y, float z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 add(Float3 a, Float3 b) {
+        Float3 res = new Float3();
+        res.x = a.x + b.x;
+        res.y = a.y + b.y;
+        res.z = a.z + b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(Float3 value) {
+        x += value.x;
+        y += value.y;
+        z += value.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(float value) {
+        x += value;
+        y += value;
+        z += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 add(Float3 a, float b) {
+        Float3 res = new Float3();
+        res.x = a.x + b;
+        res.y = a.y + b;
+        res.z = a.z + b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(Float3 value) {
+        x -= value.x;
+        y -= value.y;
+        z -= value.z;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 sub(Float3 a, Float3 b) {
+        Float3 res = new Float3();
+        res.x = a.x - b.x;
+        res.y = a.y - b.y;
+        res.z = a.z - b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(float value) {
+        x -= value;
+        y -= value;
+        z -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 sub(Float3 a, float b) {
+        Float3 res = new Float3();
+        res.x = a.x - b;
+        res.y = a.y - b;
+        res.z = a.z - b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(Float3 value) {
+        x *= value.x;
+        y *= value.y;
+        z *= value.z;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 mul(Float3 a, Float3 b) {
+        Float3 res = new Float3();
+        res.x = a.x * b.x;
+        res.y = a.y * b.y;
+        res.z = a.z * b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(float value) {
+        x *= value;
+        y *= value;
+        z *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 mul(Float3 a, float b) {
+        Float3 res = new Float3();
+        res.x = a.x * b;
+        res.y = a.y * b;
+        res.z = a.z * b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(Float3 value) {
+        x /= value.x;
+        y /= value.y;
+        z /= value.z;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 div(Float3 a, Float3 b) {
+        Float3 res = new Float3();
+        res.x = a.x / b.x;
+        res.y = a.y / b.y;
+        res.z = a.z / b.z;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(float value) {
+        x /= value;
+        y /= value;
+        z /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float3 div(Float3 a, float b) {
+        Float3 res = new Float3();
+        res.x = a.x / b;
+        res.y = a.y / b;
+        res.z = a.z / b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public Float dotProduct(Float3 a) {
+        return new Float((x * a.x) + (y * a.y) + (z * a.z));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float dotProduct(Float3 a, Float3 b) {
+        return new Float((b.x * a.x) + (b.y * a.y) + (b.z * a.z));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Float3 a, float factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+    }
+
+    /** @hide
+     * set vector value by float3
+     *
+     * @param a
+     */
+    public void set(Float3 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        x = -x;
+        y = -y;
+        z = -z;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 3;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public Float elementSum() {
+        return new Float(x + y + z);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public float get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        case 2:
+            return z;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, float value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, float value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value
+     *
+     * @param x
+     * @param y
+     * @param z
+     */
+    public void setValues(float x, float y, float z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide
+     * copy the vector to float array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(float[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+        data[offset + 2] = z;
+    }
+}
diff --git a/android/renderscript/Float4.java b/android/renderscript/Float4.java
new file mode 100644
index 0000000..7f3ba2c
--- /dev/null
+++ b/android/renderscript/Float4.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic float type.
+ * Provides four float fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Float4 {
+    public float x;
+    public float y;
+    public float z;
+    public float w;
+
+    public Float4() {
+    }
+    /** @hide */
+    public Float4(Float4 data) {
+        this.x = data.x;
+        this.y = data.y;
+        this.z = data.z;
+        this.w = data.w;
+    }
+
+    public Float4(float x, float y, float z, float w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 add(Float4 a, Float4 b) {
+        Float4 res = new Float4();
+        res.x = a.x + b.x;
+        res.y = a.y + b.y;
+        res.z = a.z + b.z;
+        res.w = a.w + b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(Float4 value) {
+        x += value.x;
+        y += value.y;
+        z += value.z;
+        w += value.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(float value) {
+        x += value;
+        y += value;
+        z += value;
+        w += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 add(Float4 a, float b) {
+        Float4 res = new Float4();
+        res.x = a.x + b;
+        res.y = a.y + b;
+        res.z = a.z + b;
+        res.w = a.w + b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(Float4 value) {
+        x -= value.x;
+        y -= value.y;
+        z -= value.z;
+        w -= value.w;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(float value) {
+        x -= value;
+        y -= value;
+        z -= value;
+        w -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 sub(Float4 a, float b) {
+        Float4 res = new Float4();
+        res.x = a.x - b;
+        res.y = a.y - b;
+        res.z = a.z - b;
+        res.w = a.w - b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 sub(Float4 a, Float4 b) {
+        Float4 res = new Float4();
+        res.x = a.x - b.x;
+        res.y = a.y - b.y;
+        res.z = a.z - b.z;
+        res.w = a.w - b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(Float4 value) {
+        x *= value.x;
+        y *= value.y;
+        z *= value.z;
+        w *= value.w;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(float value) {
+        x *= value;
+        y *= value;
+        z *= value;
+        w *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 mul(Float4 a, Float4 b) {
+        Float4 res = new Float4();
+        res.x = a.x * b.x;
+        res.y = a.y * b.y;
+        res.z = a.z * b.z;
+        res.w = a.w * b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 mul(Float4 a, float b) {
+        Float4 res = new Float4();
+        res.x = a.x * b;
+        res.y = a.y * b;
+        res.z = a.z * b;
+        res.w = a.w * b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(Float4 value) {
+        x /= value.x;
+        y /= value.y;
+        z /= value.z;
+        w /= value.w;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(float value) {
+        x /= value;
+        y /= value;
+        z /= value;
+        w /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 div(Float4 a, float b) {
+        Float4 res = new Float4();
+        res.x = a.x / b;
+        res.y = a.y / b;
+        res.z = a.z / b;
+        res.w = a.w / b;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Float4 div(Float4 a, Float4 b) {
+        Float4 res = new Float4();
+        res.x = a.x / b.x;
+        res.y = a.y / b.y;
+        res.z = a.z / b.z;
+        res.w = a.w / b.w;
+
+        return res;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public float dotProduct(Float4 a) {
+        return (x * a.x) + (y * a.y) + (z * a.z) + (w * a.w);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static float dotProduct(Float4 a, Float4 b) {
+        return (b.x * a.x) + (b.y * a.y) + (b.z * a.z) + (b.w * a.w);
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Float4 a, float factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+        w += a.w * factor;
+    }
+
+    /** @hide
+     * set vector value by float4
+     *
+     * @param a
+     */
+    public void set(Float4 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+        this.w = a.w;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        x = -x;
+        y = -y;
+        z = -z;
+        w = -w;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 4;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public float elementSum() {
+        return x + y + z + w;
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public float get(int i) {
+        switch (i) {
+        case 0:
+            return x;
+        case 1:
+            return y;
+        case 2:
+            return z;
+        case 3:
+            return w;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, float value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        case 3:
+            w = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, float value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        case 3:
+            w += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value
+     *
+     * @param x
+     * @param y
+     * @param z
+     * @param w
+     */
+    public void setValues(float x, float y, float z, float w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide
+     * copy the vector to float array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(float[] data, int offset) {
+        data[offset] = x;
+        data[offset + 1] = y;
+        data[offset + 2] = z;
+        data[offset + 3] = w;
+    }
+}
diff --git a/android/renderscript/Font.java b/android/renderscript/Font.java
new file mode 100644
index 0000000..6f6f341
--- /dev/null
+++ b/android/renderscript/Font.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Environment;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * <p>This class gives users a simple way to draw hardware accelerated text.
+ * Internally, the glyphs are rendered using the Freetype library and an internal cache of
+ * rendered glyph bitmaps is maintained. Each font object represents a combination of a typeface,
+ * and point size. You can create multiple font objects to represent styles such as bold or italic text,
+ * faces, and different font sizes. During creation, the Android system quieries device's screen DPI to
+ * ensure proper sizing across multiple device configurations.</p>
+ * <p>Fonts are rendered using screen-space positions and no state setup beyond binding a
+ * font to the RenderScript is required. A note of caution on performance, though the state changes
+ * are transparent to the user, they do happen internally, and it is more efficient to
+ * render large batches of text in sequence. It is also more efficient to render multiple
+ * characters at once instead of one by one to improve draw call batching.</p>
+ * <p>Font color and transparency are not part of the font object and you can freely modify
+ * them in the script to suit the user's rendering needs. Font colors work as a state machine.
+ * Every new call to draw text uses the last color set in the script.</p>
+ **/
+@Deprecated
+public class Font extends BaseObj {
+
+    //These help us create a font by family name
+    private static final String[] sSansNames = {
+        "sans-serif", "arial", "helvetica", "tahoma", "verdana"
+    };
+
+    private static final String[] sSerifNames = {
+        "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
+        "goudy", "fantasy", "cursive", "ITC Stone Serif"
+    };
+
+    private static final String[] sMonoNames = {
+        "monospace", "courier", "courier new", "monaco"
+    };
+
+    private static class FontFamily {
+        String[] mNames;
+        String mNormalFileName;
+        String mBoldFileName;
+        String mItalicFileName;
+        String mBoldItalicFileName;
+    }
+
+    private static Map<String, FontFamily> sFontFamilyMap;
+
+    /**
+     * @deprecated in API 16
+     */
+    public enum Style {
+        /**
+         * @deprecated in API 16
+         */
+        NORMAL,
+        /**
+         * @deprecated in API 16
+         */
+        BOLD,
+        /**
+         * @deprecated in API 16
+         */
+        @UnsupportedAppUsage
+        ITALIC,
+        /**
+         * @deprecated in API 16
+         */
+        BOLD_ITALIC;
+    }
+
+    private static void addFamilyToMap(FontFamily family) {
+        for(int i = 0; i < family.mNames.length; i ++) {
+            sFontFamilyMap.put(family.mNames[i], family);
+        }
+    }
+
+    private static void initFontFamilyMap() {
+        sFontFamilyMap = new HashMap<String, FontFamily>();
+
+        FontFamily sansFamily = new FontFamily();
+        sansFamily.mNames = sSansNames;
+        sansFamily.mNormalFileName = "Roboto-Regular.ttf";
+        sansFamily.mBoldFileName = "Roboto-Bold.ttf";
+        sansFamily.mItalicFileName = "Roboto-Italic.ttf";
+        sansFamily.mBoldItalicFileName = "Roboto-BoldItalic.ttf";
+        addFamilyToMap(sansFamily);
+
+        FontFamily serifFamily = new FontFamily();
+        serifFamily.mNames = sSerifNames;
+        serifFamily.mNormalFileName = "NotoSerif-Regular.ttf";
+        serifFamily.mBoldFileName = "NotoSerif-Bold.ttf";
+        serifFamily.mItalicFileName = "NotoSerif-Italic.ttf";
+        serifFamily.mBoldItalicFileName = "NotoSerif-BoldItalic.ttf";
+        addFamilyToMap(serifFamily);
+
+        FontFamily monoFamily = new FontFamily();
+        monoFamily.mNames = sMonoNames;
+        monoFamily.mNormalFileName = "DroidSansMono.ttf";
+        monoFamily.mBoldFileName = "DroidSansMono.ttf";
+        monoFamily.mItalicFileName = "DroidSansMono.ttf";
+        monoFamily.mBoldItalicFileName = "DroidSansMono.ttf";
+        addFamilyToMap(monoFamily);
+    }
+
+    static {
+        initFontFamilyMap();
+    }
+
+    static String getFontFileName(String familyName, Style style) {
+        FontFamily family = sFontFamilyMap.get(familyName);
+        if(family != null) {
+            switch(style) {
+                case NORMAL:
+                    return family.mNormalFileName;
+                case BOLD:
+                    return family.mBoldFileName;
+                case ITALIC:
+                    return family.mItalicFileName;
+                case BOLD_ITALIC:
+                    return family.mBoldItalicFileName;
+            }
+        }
+        // Fallback if we could not find the desired family
+        return "DroidSans.ttf";
+    }
+
+    Font(long id, RenderScript rs) {
+        super(id, rs);
+        guard.open("destroy");
+    }
+
+    /**
+     * @deprecated in API 16
+     * Takes a specific file name as an argument
+     */
+    static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize) {
+        rs.validate();
+        int dpi = res.getDisplayMetrics().densityDpi;
+        long fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
+
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from file " + path);
+        }
+        Font rsFont = new Font(fontId, rs);
+
+        return rsFont;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    static public Font createFromFile(RenderScript rs, Resources res, File path, float pointSize) {
+        return createFromFile(rs, res, path.getAbsolutePath(), pointSize);
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    static public Font createFromAsset(RenderScript rs, Resources res, String path, float pointSize) {
+        rs.validate();
+        AssetManager mgr = res.getAssets();
+        int dpi = res.getDisplayMetrics().densityDpi;
+
+        long fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from asset " + path);
+        }
+        Font rsFont = new Font(fontId, rs);
+        return rsFont;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    static public Font createFromResource(RenderScript rs, Resources res, int id, float pointSize) {
+        String name = "R." + Integer.toString(id);
+
+        rs.validate();
+        InputStream is = null;
+        try {
+            is = res.openRawResource(id);
+        } catch (Exception e) {
+            throw new RSRuntimeException("Unable to open resource " + id);
+        }
+
+        int dpi = res.getDisplayMetrics().densityDpi;
+
+        long fontId = 0;
+        if (is instanceof AssetManager.AssetInputStream) {
+            long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
+            fontId = rs.nFontCreateFromAssetStream(name, pointSize, dpi, asset);
+        } else {
+            throw new RSRuntimeException("Unsupported asset stream created");
+        }
+
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from resource " + id);
+        }
+        Font rsFont = new Font(fontId, rs);
+        return rsFont;
+    }
+
+    /**
+     * @deprecated in API 16
+     * Accepts one of the following family names as an argument
+     * and will attempt to produce the best match with a system font:
+     *
+     * "sans-serif" "arial" "helvetica" "tahoma" "verdana"
+     * "serif" "times" "times new roman" "palatino" "georgia" "baskerville"
+     * "goudy" "fantasy" "cursive" "ITC Stone Serif"
+     * "monospace" "courier" "courier new" "monaco"
+     *
+     * Returns default font if no match could be found.
+     */
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize) {
+        String fileName = getFontFileName(familyName, fontStyle);
+        String fontPath = Environment.getRootDirectory().getAbsolutePath();
+        fontPath += "/fonts/" + fileName;
+        return createFromFile(rs, res, fontPath, pointSize);
+    }
+
+}
diff --git a/android/renderscript/Int2.java b/android/renderscript/Int2.java
new file mode 100644
index 0000000..be0639f
--- /dev/null
+++ b/android/renderscript/Int2.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic int type.
+ * Provides two int fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Int2 {
+    public int x;
+    public int y;
+
+    public Int2() {
+    }
+
+    /** @hide */
+    public Int2(int i) {
+        this.x = this.y = i;
+    }
+
+    public Int2(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide */
+    public Int2(Int2 source) {
+        this.x = source.x;
+        this.y = source.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Int2 a) {
+        this.x += a.x;
+        this.y += a.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 add(Int2 a, Int2 b) {
+        Int2 result = new Int2();
+        result.x = a.x + b.x;
+        result.y = a.y + b.y;
+
+        return result;
+    }
+
+    /**  @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(int value) {
+        x += value;
+        y += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 add(Int2 a, int b) {
+        Int2 result = new Int2();
+        result.x = a.x + b;
+        result.y = a.y + b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Int2 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 sub(Int2 a, Int2 b) {
+        Int2 result = new Int2();
+        result.x = a.x - b.x;
+        result.y = a.y - b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(int value) {
+        x -= value;
+        y -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 sub(Int2 a, int b) {
+        Int2 result = new Int2();
+        result.x = a.x - b;
+        result.y = a.y - b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Int2 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 mul(Int2 a, Int2 b) {
+        Int2 result = new Int2();
+        result.x = a.x * b.x;
+        result.y = a.y * b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(int value) {
+        x *= value;
+        y *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 mul(Int2 a, int b) {
+        Int2 result = new Int2();
+        result.x = a.x * b;
+        result.y = a.y * b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Int2 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 div(Int2 a, Int2 b) {
+        Int2 result = new Int2();
+        result.x = a.x / b.x;
+        result.y = a.y / b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(int value) {
+        x /= value;
+        y /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 div(Int2 a, int b) {
+        Int2 result = new Int2();
+        result.x = a.x / b;
+        result.y = a.y / b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Int2 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 mod(Int2 a, Int2 b) {
+        Int2 result = new Int2();
+        result.x = a.x % b.x;
+        result.y = a.y % b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(int value) {
+        x %= value;
+        y %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int2 mod(Int2 a, int b) {
+        Int2 result = new Int2();
+        result.x = a.x % b;
+        result.y = a.y % b;
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 2;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = -x;
+        this.y = -y;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public int dotProduct(Int2 a) {
+        return (int)((x * a.x) + (y * a.y));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static int dotProduct(Int2 a, Int2 b) {
+        return (int)((b.x * a.x) + (b.y * a.y));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Int2 a, int factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+    }
+
+    /** @hide
+     * set vector value by Int2
+     *
+     * @param a
+     */
+    public void set(Int2 a) {
+        this.x = a.x;
+        this.y = a.y;
+    }
+
+    /** @hide
+     * set the vector field value by Int
+     *
+     * @param a
+     * @param b
+     */
+    public void setValues(int a, int b) {
+        this.x = a;
+        this.y = b;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public int elementSum() {
+        return (int)(x + y);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public int get(int i) {
+        switch (i) {
+        case 0:
+            return (int)(x);
+        case 1:
+            return (int)(y);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, int value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, int value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to int array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(int[] data, int offset) {
+        data[offset] = (int)(x);
+        data[offset + 1] = (int)(y);
+    }
+}
diff --git a/android/renderscript/Int3.java b/android/renderscript/Int3.java
new file mode 100644
index 0000000..38a602d
--- /dev/null
+++ b/android/renderscript/Int3.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic int type.
+ * Provides three int fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Int3 {
+    public int x;
+    public int y;
+    public int z;
+
+    public Int3() {
+    }
+
+    /** @hide */
+    public Int3(int i) {
+        this.x = this.y = this.z = i;
+    }
+
+    public Int3(int x, int y, int z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide */
+    public Int3(Int3 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Int3 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 add(Int3 a, Int3 b) {
+        Int3 result = new Int3();
+        result.x = a.x + b.x;
+        result.y = a.y + b.y;
+        result.z = a.z + b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(int value) {
+        x += value;
+        y += value;
+        z += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 add(Int3 a, int b) {
+        Int3 result = new Int3();
+        result.x = a.x + b;
+        result.y = a.y + b;
+        result.z = a.z + b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Int3 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 sub(Int3 a, Int3 b) {
+        Int3 result = new Int3();
+        result.x = a.x - b.x;
+        result.y = a.y - b.y;
+        result.z = a.z - b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(int value) {
+        x -= value;
+        y -= value;
+        z -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 sub(Int3 a, int b) {
+        Int3 result = new Int3();
+        result.x = a.x - b;
+        result.y = a.y - b;
+        result.z = a.z - b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Int3 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 mul(Int3 a, Int3 b) {
+        Int3 result = new Int3();
+        result.x = a.x * b.x;
+        result.y = a.y * b.y;
+        result.z = a.z * b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(int value) {
+        x *= value;
+        y *= value;
+        z *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 mul(Int3 a, int b) {
+        Int3 result = new Int3();
+        result.x = a.x * b;
+        result.y = a.y * b;
+        result.z = a.z * b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Int3 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 div(Int3 a, Int3 b) {
+        Int3 result = new Int3();
+        result.x = a.x / b.x;
+        result.y = a.y / b.y;
+        result.z = a.z / b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(int value) {
+        x /= value;
+        y /= value;
+        z /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 div(Int3 a, int b) {
+        Int3 result = new Int3();
+        result.x = a.x / b;
+        result.y = a.y / b;
+        result.z = a.z / b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Int3 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+        this.z %= a.z;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 mod(Int3 a, Int3 b) {
+        Int3 result = new Int3();
+        result.x = a.x % b.x;
+        result.y = a.y % b.y;
+        result.z = a.z % b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(int value) {
+        x %= value;
+        y %= value;
+        z %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int3 mod(Int3 a, int b) {
+        Int3 result = new Int3();
+        result.x = a.x % b;
+        result.y = a.y % b;
+        result.z = a.z % b;
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 3;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = -x;
+        this.y = -y;
+        this.z = -z;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public int dotProduct(Int3 a) {
+        return (int)((x * a.x) + (y * a.y) + (z * a.z));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static int dotProduct(Int3 a, Int3 b) {
+        return (int)((b.x * a.x) + (b.y * a.y) + (b.z * a.z));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Int3 a, int factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+    }
+
+    /** @hide
+     * set vector value by Int3
+     *
+     * @param a
+     */
+    public void set(Int3 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+    }
+
+    /** @hide
+     * set the vector field value by Int
+     *
+     * @param a
+     * @param b
+     * @param c
+     */
+    public void setValues(int a, int b, int c) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public int elementSum() {
+        return (int)(x + y + z);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public int get(int i) {
+        switch (i) {
+        case 0:
+            return (int)(x);
+        case 1:
+            return (int)(y);
+        case 2:
+            return (int)(z);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, int value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, int value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to int array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(int[] data, int offset) {
+        data[offset] = (int)(x);
+        data[offset + 1] = (int)(y);
+        data[offset + 2] = (int)(z);
+    }
+}
diff --git a/android/renderscript/Int4.java b/android/renderscript/Int4.java
new file mode 100644
index 0000000..52f7bb2
--- /dev/null
+++ b/android/renderscript/Int4.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic int type.
+ * Provides four int fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Int4 {
+    public int x;
+    public int y;
+    public int z;
+    public int w;
+
+    public Int4() {
+    }
+
+    /** @hide */
+    public Int4(int i) {
+        this.x = this.y = this.z = this.w = i;
+    }
+
+    public Int4(int x, int y, int z, int w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide */
+    public Int4(Int4 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+        this.w = source.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Int4 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+        this.w += a.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 add(Int4 a, Int4 b) {
+        Int4 result = new Int4();
+        result.x = a.x + b.x;
+        result.y = a.y + b.y;
+        result.z = a.z + b.z;
+        result.w = a.w + b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(int value) {
+        x += value;
+        y += value;
+        z += value;
+        w += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 add(Int4 a, int b) {
+        Int4 result = new Int4();
+        result.x = a.x + b;
+        result.y = a.y + b;
+        result.z = a.z + b;
+        result.w = a.w + b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Int4 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+        this.w -= a.w;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 sub(Int4 a, Int4 b) {
+        Int4 result = new Int4();
+        result.x = a.x - b.x;
+        result.y = a.y - b.y;
+        result.z = a.z - b.z;
+        result.w = a.w - b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(int value) {
+        x -= value;
+        y -= value;
+        z -= value;
+        w -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 sub(Int4 a, int b) {
+        Int4 result = new Int4();
+        result.x = a.x - b;
+        result.y = a.y - b;
+        result.z = a.z - b;
+        result.w = a.w - b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Int4 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+        this.w *= a.w;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 mul(Int4 a, Int4 b) {
+        Int4 result = new Int4();
+        result.x = a.x * b.x;
+        result.y = a.y * b.y;
+        result.z = a.z * b.z;
+        result.w = a.w * b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(int value) {
+        x *= value;
+        y *= value;
+        z *= value;
+        w *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 mul(Int4 a, int b) {
+        Int4 result = new Int4();
+        result.x = a.x * b;
+        result.y = a.y * b;
+        result.z = a.z * b;
+        result.w = a.w * b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Int4 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+        this.w /= a.w;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 div(Int4 a, Int4 b) {
+        Int4 result = new Int4();
+        result.x = a.x / b.x;
+        result.y = a.y / b.y;
+        result.z = a.z / b.z;
+        result.w = a.w / b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(int value) {
+        x /= value;
+        y /= value;
+        z /= value;
+        w /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 div(Int4 a, int b) {
+        Int4 result = new Int4();
+        result.x = a.x / b;
+        result.y = a.y / b;
+        result.z = a.z / b;
+        result.w = a.w / b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Int4 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+        this.z %= a.z;
+        this.w %= a.w;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 mod(Int4 a, Int4 b) {
+        Int4 result = new Int4();
+        result.x = a.x % b.x;
+        result.y = a.y % b.y;
+        result.z = a.z % b.z;
+        result.w = a.w % b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(int value) {
+        x %= value;
+        y %= value;
+        z %= value;
+        w %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Int4 mod(Int4 a, int b) {
+        Int4 result = new Int4();
+        result.x = a.x % b;
+        result.y = a.y % b;
+        result.z = a.z % b;
+        result.w = a.w % b;
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public int length() {
+        return 4;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = -x;
+        this.y = -y;
+        this.z = -z;
+        this.w = -w;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public int dotProduct(Int4 a) {
+        return (int)((x * a.x) + (y * a.y) + (z * a.z) + (w * a.w));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static int dotProduct(Int4 a, Int4 b) {
+        return (int)((b.x * a.x) + (b.y * a.y) + (b.z * a.z) + (b.w * a.w));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Int4 a, int factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+        w += a.w * factor;
+    }
+
+    /** @hide
+     * set vector value by Int4
+     *
+     * @param a
+     */
+    public void set(Int4 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+        this.w = a.w;
+    }
+
+    /** @hide
+     * set the vector field value by Int
+     *
+     * @param a
+     * @param b
+     * @param c
+     * @param d
+     */
+    public void setValues(int a, int b, int c, int d) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+        this.w = d;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public int elementSum() {
+        return (int)(x + y + z + w);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public int get(int i) {
+        switch (i) {
+        case 0:
+            return (int)(x);
+        case 1:
+            return (int)(y);
+        case 2:
+            return (int)(z);
+        case 3:
+            return (int)(w);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, int value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        case 3:
+            w = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, int value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        case 3:
+            w += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to int array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(int[] data, int offset) {
+        data[offset] = (int)(x);
+        data[offset + 1] = (int)(y);
+        data[offset + 2] = (int)(z);
+        data[offset + 3] = (int)(w);
+    }
+}
diff --git a/android/renderscript/Long2.java b/android/renderscript/Long2.java
new file mode 100644
index 0000000..1b3955b
--- /dev/null
+++ b/android/renderscript/Long2.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic long type.
+ * Provides two long fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Long2 {
+    public long x;
+    public long y;
+
+    public Long2() {
+    }
+
+    /** @hide */
+    public Long2(long i) {
+        this.x = this.y = i;
+    }
+
+    public Long2(long x, long y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide */
+    public Long2(Long2 source) {
+        this.x = source.x;
+        this.y = source.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Long2 a) {
+        this.x += a.x;
+        this.y += a.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 add(Long2 a, Long2 b) {
+        Long2 result = new Long2();
+        result.x = a.x + b.x;
+        result.y = a.y + b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(long value) {
+        x += value;
+        y += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 add(Long2 a, long b) {
+        Long2 result = new Long2();
+        result.x = a.x + b;
+        result.y = a.y + b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Long2 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 sub(Long2 a, Long2 b) {
+        Long2 result = new Long2();
+        result.x = a.x - b.x;
+        result.y = a.y - b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(long value) {
+        x -= value;
+        y -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 sub(Long2 a, long b) {
+        Long2 result = new Long2();
+        result.x = a.x - b;
+        result.y = a.y - b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Long2 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 mul(Long2 a, Long2 b) {
+        Long2 result = new Long2();
+        result.x = a.x * b.x;
+        result.y = a.y * b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(long value) {
+        x *= value;
+        y *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 mul(Long2 a, long b) {
+        Long2 result = new Long2();
+        result.x = a.x * b;
+        result.y = a.y * b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Long2 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 div(Long2 a, Long2 b) {
+        Long2 result = new Long2();
+        result.x = a.x / b.x;
+        result.y = a.y / b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(long value) {
+        x /= value;
+        y /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 div(Long2 a, long b) {
+        Long2 result = new Long2();
+        result.x = a.x / b;
+        result.y = a.y / b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Long2 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 mod(Long2 a, Long2 b) {
+        Long2 result = new Long2();
+        result.x = a.x % b.x;
+        result.y = a.y % b.y;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(long value) {
+        x %= value;
+        y %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long2 mod(Long2 a, long b) {
+        Long2 result = new Long2();
+        result.x = a.x % b;
+        result.y = a.y % b;
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public long length() {
+        return 2;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = -x;
+        this.y = -y;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public long dotProduct(Long2 a) {
+        return (long)((x * a.x) + (y * a.y));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static long dotProduct(Long2 a, Long2 b) {
+        return (long)((b.x * a.x) + (b.y * a.y));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Long2 a, long factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+    }
+
+    /** @hide
+     * set vector value by Long2
+     *
+     * @param a
+     */
+    public void set(Long2 a) {
+        this.x = a.x;
+        this.y = a.y;
+    }
+
+    /** @hide
+     * set the vector field value by Long
+     *
+     * @param a
+     * @param b
+     */
+    public void setValues(long a, long b) {
+        this.x = a;
+        this.y = b;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public long elementSum() {
+        return (long)(x + y);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public long get(int i) {
+        switch (i) {
+        case 0:
+            return (long)(x);
+        case 1:
+            return (long)(y);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, long value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, long value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to long array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(long[] data, int offset) {
+        data[offset] = (long)(x);
+        data[offset + 1] = (long)(y);
+    }
+}
diff --git a/android/renderscript/Long3.java b/android/renderscript/Long3.java
new file mode 100644
index 0000000..8be9c1c
--- /dev/null
+++ b/android/renderscript/Long3.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic long type.
+ * Provides three long fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Long3 {
+    public long x;
+    public long y;
+    public long z;
+
+    public Long3() {
+    }
+
+    /** @hide */
+    public Long3(long i) {
+        this.x = this.y = this.z = i;
+    }
+
+    public Long3(long x, long y, long z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide */
+    public Long3(Long3 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Long3 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 add(Long3 a, Long3 b) {
+        Long3 result = new Long3();
+        result.x = a.x + b.x;
+        result.y = a.y + b.y;
+        result.z = a.z + b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(long value) {
+        x += value;
+        y += value;
+        z += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 add(Long3 a, long b) {
+        Long3 result = new Long3();
+        result.x = a.x + b;
+        result.y = a.y + b;
+        result.z = a.z + b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Long3 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 sub(Long3 a, Long3 b) {
+        Long3 result = new Long3();
+        result.x = a.x - b.x;
+        result.y = a.y - b.y;
+        result.z = a.z - b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(long value) {
+        x -= value;
+        y -= value;
+        z -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 sub(Long3 a, long b) {
+        Long3 result = new Long3();
+        result.x = a.x - b;
+        result.y = a.y - b;
+        result.z = a.z - b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Long3 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 mul(Long3 a, Long3 b) {
+        Long3 result = new Long3();
+        result.x = a.x * b.x;
+        result.y = a.y * b.y;
+        result.z = a.z * b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(long value) {
+        x *= value;
+        y *= value;
+        z *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 mul(Long3 a, long b) {
+        Long3 result = new Long3();
+        result.x = a.x * b;
+        result.y = a.y * b;
+        result.z = a.z * b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Long3 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 div(Long3 a, Long3 b) {
+        Long3 result = new Long3();
+        result.x = a.x / b.x;
+        result.y = a.y / b.y;
+        result.z = a.z / b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(long value) {
+        x /= value;
+        y /= value;
+        z /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 div(Long3 a, long b) {
+        Long3 result = new Long3();
+        result.x = a.x / b;
+        result.y = a.y / b;
+        result.z = a.z / b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Long3 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+        this.z %= a.z;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 mod(Long3 a, Long3 b) {
+        Long3 result = new Long3();
+        result.x = a.x % b.x;
+        result.y = a.y % b.y;
+        result.z = a.z % b.z;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(long value) {
+        x %= value;
+        y %= value;
+        z %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long3 mod(Long3 a, long b) {
+        Long3 result = new Long3();
+        result.x = a.x % b;
+        result.y = a.y % b;
+        result.z = a.z % b;
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public long length() {
+        return 3;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = -x;
+        this.y = -y;
+        this.z = -z;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public long dotProduct(Long3 a) {
+        return (long)((x * a.x) + (y * a.y) + (z * a.z));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static long dotProduct(Long3 a, Long3 b) {
+        return (long)((b.x * a.x) + (b.y * a.y) + (b.z * a.z));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Long3 a, long factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+    }
+
+    /** @hide
+     * set vector value by Long3
+     *
+     * @param a
+     */
+    public void set(Long3 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+    }
+
+    /** @hide
+     * set the vector field value by Long
+     *
+     * @param a
+     * @param b
+     * @param c
+     */
+    public void setValues(long a, long b, long c) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public long elementSum() {
+        return (long)(x + y + z);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public long get(int i) {
+        switch (i) {
+        case 0:
+            return (long)(x);
+        case 1:
+            return (long)(y);
+        case 2:
+            return (long)(z);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, long value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, long value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to long array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(long[] data, int offset) {
+        data[offset] = (long)(x);
+        data[offset + 1] = (long)(y);
+        data[offset + 2] = (long)(z);
+    }
+}
diff --git a/android/renderscript/Long4.java b/android/renderscript/Long4.java
new file mode 100644
index 0000000..75db51b
--- /dev/null
+++ b/android/renderscript/Long4.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic long type.
+ * Provides four long fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Long4 {
+    public long x;
+    public long y;
+    public long z;
+    public long w;
+
+    public Long4() {
+    }
+
+    /** @hide */
+    public Long4(long i) {
+        this.x = this.y = this.z = this.w = i;
+    }
+
+    public Long4(long x, long y, long z, long w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide */
+    public Long4(Long4 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+        this.w = source.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Long4 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+        this.w += a.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 add(Long4 a, Long4 b) {
+        Long4 result = new Long4();
+        result.x = a.x + b.x;
+        result.y = a.y + b.y;
+        result.z = a.z + b.z;
+        result.w = a.w + b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(long value) {
+        x += value;
+        y += value;
+        z += value;
+        w += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 add(Long4 a, long b) {
+        Long4 result = new Long4();
+        result.x = a.x + b;
+        result.y = a.y + b;
+        result.z = a.z + b;
+        result.w = a.w + b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Long4 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+        this.w -= a.w;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 sub(Long4 a, Long4 b) {
+        Long4 result = new Long4();
+        result.x = a.x - b.x;
+        result.y = a.y - b.y;
+        result.z = a.z - b.z;
+        result.w = a.w - b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(long value) {
+        x -= value;
+        y -= value;
+        z -= value;
+        w -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 sub(Long4 a, long b) {
+        Long4 result = new Long4();
+        result.x = a.x - b;
+        result.y = a.y - b;
+        result.z = a.z - b;
+        result.w = a.w - b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Long4 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+        this.w *= a.w;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 mul(Long4 a, Long4 b) {
+        Long4 result = new Long4();
+        result.x = a.x * b.x;
+        result.y = a.y * b.y;
+        result.z = a.z * b.z;
+        result.w = a.w * b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(long value) {
+        x *= value;
+        y *= value;
+        z *= value;
+        w *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 mul(Long4 a, long b) {
+        Long4 result = new Long4();
+        result.x = a.x * b;
+        result.y = a.y * b;
+        result.z = a.z * b;
+        result.w = a.w * b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Long4 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+        this.w /= a.w;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 div(Long4 a, Long4 b) {
+        Long4 result = new Long4();
+        result.x = a.x / b.x;
+        result.y = a.y / b.y;
+        result.z = a.z / b.z;
+        result.w = a.w / b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(long value) {
+        x /= value;
+        y /= value;
+        z /= value;
+        w /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 div(Long4 a, long b) {
+        Long4 result = new Long4();
+        result.x = a.x / b;
+        result.y = a.y / b;
+        result.z = a.z / b;
+        result.w = a.w / b;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Long4 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+        this.z %= a.z;
+        this.w %= a.w;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 mod(Long4 a, Long4 b) {
+        Long4 result = new Long4();
+        result.x = a.x % b.x;
+        result.y = a.y % b.y;
+        result.z = a.z % b.z;
+        result.w = a.w % b.w;
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(long value) {
+        x %= value;
+        y %= value;
+        z %= value;
+        w %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Long4 mod(Long4 a, long b) {
+        Long4 result = new Long4();
+        result.x = a.x % b;
+        result.y = a.y % b;
+        result.z = a.z % b;
+        result.w = a.w % b;
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public long length() {
+        return 4;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = -x;
+        this.y = -y;
+        this.z = -z;
+        this.w = -w;
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public long dotProduct(Long4 a) {
+        return (long)((x * a.x) + (y * a.y) + (z * a.z) + (w * a.w));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static long dotProduct(Long4 a, Long4 b) {
+        return (long)((b.x * a.x) + (b.y * a.y) + (b.z * a.z) + (b.w * a.w));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Long4 a, long factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+        w += a.w * factor;
+    }
+
+    /** @hide
+     * set vector value by Long4
+     *
+     * @param a
+     */
+    public void set(Long4 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+        this.w = a.w;
+    }
+
+    /** @hide
+     * set the vector field value by Long
+     *
+     * @param a
+     * @param b
+     * @param c
+     * @param d
+     */
+    public void setValues(long a, long b, long c, long d) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+        this.w = d;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public long elementSum() {
+        return (long)(x + y + z + w);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public long get(int i) {
+        switch (i) {
+        case 0:
+            return (long)(x);
+        case 1:
+            return (long)(y);
+        case 2:
+            return (long)(z);
+        case 3:
+            return (long)(w);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, long value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        case 3:
+            w = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, long value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        case 3:
+            w += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to long array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(long[] data, int offset) {
+        data[offset] = (long)(x);
+        data[offset + 1] = (long)(y);
+        data[offset + 2] = (long)(z);
+        data[offset + 3] = (long)(w);
+    }
+}
diff --git a/android/renderscript/Matrix2f.java b/android/renderscript/Matrix2f.java
new file mode 100644
index 0000000..5f5e709
--- /dev/null
+++ b/android/renderscript/Matrix2f.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2009-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Class for exposing the native RenderScript rs_matrix2x2 type back to the Android system.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Matrix2f {
+
+    /**
+    * Creates a new identity 2x2 matrix
+    */
+    public Matrix2f() {
+        mMat = new float[4];
+        loadIdentity();
+    }
+
+    /**
+    * Creates a new matrix and sets its values from the given
+    * parameter
+    *
+    * @param dataArray values to set the matrix to, must be 4
+    *                  floats long
+    */
+    public Matrix2f(float[] dataArray) {
+        mMat = new float[4];
+        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
+    }
+
+    /**
+    * Return a reference to the internal array representing matrix
+    * values. Modifying this array will also change the matrix
+    *
+    * @return internal array representing the matrix
+    */
+    public float[] getArray() {
+        return mMat;
+    }
+
+    /**
+    * Returns the value for a given row and column
+    *
+    * @param x column of the value to return
+    * @param y row of the value to return
+    *
+    * @return value in the yth row and xth column
+    */
+    public float get(int x, int y) {
+        return mMat[x*2 + y];
+    }
+
+    /**
+    * Sets the value for a given row and column
+    *
+    * @param x column of the value to set
+    * @param y row of the value to set
+    */
+    public void set(int x, int y, float v) {
+        mMat[x*2 + y] = v;
+    }
+
+    /**
+    * Sets the matrix values to identity
+    */
+    public void loadIdentity() {
+        mMat[0] = 1;
+        mMat[1] = 0;
+
+        mMat[2] = 0;
+        mMat[3] = 1;
+    }
+
+    /**
+    * Sets the values of the matrix to those of the parameter
+    *
+    * @param src matrix to load the values from
+    */
+    public void load(Matrix2f src) {
+        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
+    }
+
+    /**
+    * Sets current values to be a rotation matrix of given angle
+    *
+    * @param rot rotation angle
+    */
+    public void loadRotate(float rot) {
+        float c, s;
+        rot *= (float)(java.lang.Math.PI / 180.0f);
+        c = (float)java.lang.Math.cos(rot);
+        s = (float)java.lang.Math.sin(rot);
+        mMat[0] = c;
+        mMat[1] = -s;
+        mMat[2] = s;
+        mMat[3] = c;
+    }
+
+    /**
+    * Sets current values to be a scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    */
+    public void loadScale(float x, float y) {
+        loadIdentity();
+        mMat[0] = x;
+        mMat[3] = y;
+    }
+
+    /**
+    * Sets current values to be the result of multiplying two given
+    * matrices
+    *
+    * @param lhs left hand side matrix
+    * @param rhs right hand side matrix
+    */
+    public void loadMultiply(Matrix2f lhs, Matrix2f rhs) {
+        for (int i=0 ; i<2 ; i++) {
+            float ri0 = 0;
+            float ri1 = 0;
+            for (int j=0 ; j<2 ; j++) {
+                float rhs_ij = rhs.get(i,j);
+                ri0 += lhs.get(j,0) * rhs_ij;
+                ri1 += lhs.get(j,1) * rhs_ij;
+            }
+            set(i,0, ri0);
+            set(i,1, ri1);
+        }
+    }
+
+    /**
+    * Post-multiplies the current matrix by a given parameter
+    *
+    * @param rhs right hand side to multiply by
+    */
+    public void multiply(Matrix2f rhs) {
+        Matrix2f tmp = new Matrix2f();
+        tmp.loadMultiply(this, rhs);
+        load(tmp);
+    }
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * rotation matrix of given angle
+    *
+    * @param rot angle of rotation
+    */
+    public void rotate(float rot) {
+        Matrix2f tmp = new Matrix2f();
+        tmp.loadRotate(rot);
+        multiply(tmp);
+    }
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    */
+    public void scale(float x, float y) {
+        Matrix2f tmp = new Matrix2f();
+        tmp.loadScale(x, y);
+        multiply(tmp);
+    }
+    /**
+    * Sets the current matrix to its transpose
+    */
+    public void transpose() {
+        float temp = mMat[1];
+        mMat[1] = mMat[2];
+        mMat[2] = temp;
+    }
+
+    final float[] mMat;
+}
+
+
+
diff --git a/android/renderscript/Matrix3f.java b/android/renderscript/Matrix3f.java
new file mode 100644
index 0000000..b620eaf
--- /dev/null
+++ b/android/renderscript/Matrix3f.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2009-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Class for exposing the native RenderScript rs_matrix3x3 type back to the Android system.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Matrix3f {
+
+    /**
+    * Creates a new identity 3x3 matrix
+    */
+    public Matrix3f() {
+        mMat = new float[9];
+        loadIdentity();
+    }
+
+    /**
+    * Creates a new matrix and sets its values from the given
+    * parameter
+    *
+    * @param dataArray values to set the matrix to, must be 9
+    *                  floats long
+    */
+    public Matrix3f(float[] dataArray) {
+        mMat = new float[9];
+        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
+    }
+
+    /**
+    * Return a reference to the internal array representing matrix
+    * values. Modifying this array will also change the matrix
+    *
+    * @return internal array representing the matrix
+    */
+    public float[] getArray() {
+        return mMat;
+    }
+
+    /**
+    * Returns the value for a given row and column
+    *
+    * @param x column of the value to return
+    * @param y row of the value to return
+    *
+    * @return value in the yth row and xth column
+    */
+    public float get(int x, int y) {
+        return mMat[x*3 + y];
+    }
+
+    /**
+    * Sets the value for a given row and column
+    *
+    * @param x column of the value to set
+    * @param y row of the value to set
+    */
+    public void set(int x, int y, float v) {
+        mMat[x*3 + y] = v;
+    }
+
+    /**
+    * Sets the matrix values to identity
+    */
+    public void loadIdentity() {
+        mMat[0] = 1;
+        mMat[1] = 0;
+        mMat[2] = 0;
+
+        mMat[3] = 0;
+        mMat[4] = 1;
+        mMat[5] = 0;
+
+        mMat[6] = 0;
+        mMat[7] = 0;
+        mMat[8] = 1;
+    }
+
+    /**
+    * Sets the values of the matrix to those of the parameter
+    *
+    * @param src matrix to load the values from
+    */
+    public void load(Matrix3f src) {
+        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
+    }
+
+    /**
+    * Sets current values to be a rotation matrix of certain angle
+    * about a given axis
+    *
+    * @param rot angle of rotation
+    * @param x rotation axis x
+    * @param y rotation axis y
+    * @param z rotation axis z
+    */
+    public void loadRotate(float rot, float x, float y, float z) {
+        float c, s;
+        rot *= (float)(java.lang.Math.PI / 180.0f);
+        c = (float)java.lang.Math.cos(rot);
+        s = (float)java.lang.Math.sin(rot);
+
+        float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
+        if (!(len != 1)) {
+            float recipLen = 1.f / len;
+            x *= recipLen;
+            y *= recipLen;
+            z *= recipLen;
+        }
+        float nc = 1.0f - c;
+        float xy = x * y;
+        float yz = y * z;
+        float zx = z * x;
+        float xs = x * s;
+        float ys = y * s;
+        float zs = z * s;
+        mMat[0] = x*x*nc +  c;
+        mMat[3] =  xy*nc - zs;
+        mMat[6] =  zx*nc + ys;
+        mMat[1] =  xy*nc + zs;
+        mMat[4] = y*y*nc +  c;
+        mMat[7] =  yz*nc - xs;
+        mMat[2] =  zx*nc - ys;
+        mMat[5] =  yz*nc + xs;
+        mMat[8] = z*z*nc +  c;
+    }
+
+    /**
+    * Makes the upper 2x2 a rotation matrix of the given angle
+    *
+    * @param rot rotation angle
+    */
+    public void loadRotate(float rot) {
+        loadIdentity();
+        float c, s;
+        rot *= (float)(java.lang.Math.PI / 180.0f);
+        c = (float)java.lang.Math.cos(rot);
+        s = (float)java.lang.Math.sin(rot);
+        mMat[0] = c;
+        mMat[1] = -s;
+        mMat[3] = s;
+        mMat[4] = c;
+    }
+
+    /**
+    * Makes the upper 2x2 a scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    */
+    public void loadScale(float x, float y) {
+        loadIdentity();
+        mMat[0] = x;
+        mMat[4] = y;
+    }
+
+    /**
+    * Sets current values to be a scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    * @param z scale component z
+    */
+    public void loadScale(float x, float y, float z) {
+        loadIdentity();
+        mMat[0] = x;
+        mMat[4] = y;
+        mMat[8] = z;
+    }
+
+    /**
+    * Sets current values to be a translation matrix of given
+    * dimensions
+    *
+    * @param x translation component x
+    * @param y translation component y
+    */
+    public void loadTranslate(float x, float y) {
+        loadIdentity();
+        mMat[6] = x;
+        mMat[7] = y;
+    }
+
+    /**
+    * Sets current values to be the result of multiplying two given
+    * matrices
+    *
+    * @param lhs left hand side matrix
+    * @param rhs right hand side matrix
+    */
+    public void loadMultiply(Matrix3f lhs, Matrix3f rhs) {
+        for (int i=0 ; i<3 ; i++) {
+            float ri0 = 0;
+            float ri1 = 0;
+            float ri2 = 0;
+            for (int j=0 ; j<3 ; j++) {
+                float rhs_ij = rhs.get(i,j);
+                ri0 += lhs.get(j,0) * rhs_ij;
+                ri1 += lhs.get(j,1) * rhs_ij;
+                ri2 += lhs.get(j,2) * rhs_ij;
+            }
+            set(i,0, ri0);
+            set(i,1, ri1);
+            set(i,2, ri2);
+        }
+    }
+
+    /**
+    * Post-multiplies the current matrix by a given parameter
+    *
+    * @param rhs right hand side to multiply by
+    */
+    public void multiply(Matrix3f rhs) {
+        Matrix3f tmp = new Matrix3f();
+        tmp.loadMultiply(this, rhs);
+        load(tmp);
+    }
+
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * rotation matrix of certain angle about a given axis
+    *
+    * @param rot angle of rotation
+    * @param x rotation axis x
+    * @param y rotation axis y
+    * @param z rotation axis z
+    */
+    public void rotate(float rot, float x, float y, float z) {
+        Matrix3f tmp = new Matrix3f();
+        tmp.loadRotate(rot, x, y, z);
+        multiply(tmp);
+    }
+
+    /**
+    * Modifies the upper 2x2 of the current matrix by
+    * post-multiplying it with a rotation matrix of given angle
+    *
+    * @param rot angle of rotation
+    */
+    public void rotate(float rot) {
+        Matrix3f tmp = new Matrix3f();
+        tmp.loadRotate(rot);
+        multiply(tmp);
+    }
+
+    /**
+    * Modifies the upper 2x2 of the current matrix by
+    * post-multiplying it with a scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    */
+    public void scale(float x, float y) {
+        Matrix3f tmp = new Matrix3f();
+        tmp.loadScale(x, y);
+        multiply(tmp);
+    }
+
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    * @param z scale component z
+    */
+    public void scale(float x, float y, float z) {
+        Matrix3f tmp = new Matrix3f();
+        tmp.loadScale(x, y, z);
+        multiply(tmp);
+    }
+
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * translation matrix of given dimensions
+    *
+    * @param x translation component x
+    * @param y translation component y
+    */
+    public void translate(float x, float y) {
+        Matrix3f tmp = new Matrix3f();
+        tmp.loadTranslate(x, y);
+        multiply(tmp);
+    }
+
+    /**
+    * Sets the current matrix to its transpose
+    */
+    public void transpose() {
+        for(int i = 0; i < 2; ++i) {
+            for(int j = i + 1; j < 3; ++j) {
+                float temp = mMat[i*3 + j];
+                mMat[i*3 + j] = mMat[j*3 + i];
+                mMat[j*3 + i] = temp;
+            }
+        }
+    }
+
+    final float[] mMat;
+}
+
+
diff --git a/android/renderscript/Matrix4f.java b/android/renderscript/Matrix4f.java
new file mode 100644
index 0000000..cdf06a6
--- /dev/null
+++ b/android/renderscript/Matrix4f.java
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2009-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+
+/**
+ * Class for exposing the native RenderScript rs_matrix4x4 type back to the Android system.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Matrix4f {
+
+    /**
+    * Creates a new identity 4x4 matrix
+    */
+    public Matrix4f() {
+        mMat = new float[16];
+        loadIdentity();
+    }
+
+    /**
+    * Creates a new matrix and sets its values from the given
+    * parameter
+    *
+    * @param dataArray values to set the matrix to, must be 16
+    *                  floats long
+    */
+    public Matrix4f(float[] dataArray) {
+        mMat = new float[16];
+        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
+    }
+
+    /**
+    * Return a reference to the internal array representing matrix
+    * values. Modifying this array will also change the matrix
+    *
+    * @return internal array representing the matrix
+    */
+    public float[] getArray() {
+        return mMat;
+    }
+
+    /**
+    * Returns the value for a given row and column
+    *
+    * @param x column of the value to return
+    * @param y row of the value to return
+    *
+    * @return value in the yth row and xth column
+    */
+    public float get(int x, int y) {
+        return mMat[x*4 + y];
+    }
+
+    /**
+    * Sets the value for a given row and column
+    *
+    * @param x column of the value to set
+    * @param y row of the value to set
+    */
+    public void set(int x, int y, float v) {
+        mMat[x*4 + y] = v;
+    }
+
+    /**
+    * Sets the matrix values to identity
+    */
+    public void loadIdentity() {
+        mMat[0] = 1;
+        mMat[1] = 0;
+        mMat[2] = 0;
+        mMat[3] = 0;
+
+        mMat[4] = 0;
+        mMat[5] = 1;
+        mMat[6] = 0;
+        mMat[7] = 0;
+
+        mMat[8] = 0;
+        mMat[9] = 0;
+        mMat[10] = 1;
+        mMat[11] = 0;
+
+        mMat[12] = 0;
+        mMat[13] = 0;
+        mMat[14] = 0;
+        mMat[15] = 1;
+    }
+
+    /**
+    * Sets the values of the matrix to those of the parameter
+    *
+    * @param src matrix to load the values from
+    */
+    public void load(Matrix4f src) {
+        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
+    }
+
+    /**
+    * Sets the values of the matrix to those of the parameter
+    *
+    * @param src matrix to load the values from
+    * @hide
+    */
+    public void load(Matrix3f src) {
+        mMat[0] = src.mMat[0];
+        mMat[1] = src.mMat[1];
+        mMat[2] = src.mMat[2];
+        mMat[3] = 0;
+
+        mMat[4] = src.mMat[3];
+        mMat[5] = src.mMat[4];
+        mMat[6] = src.mMat[5];
+        mMat[7] = 0;
+
+        mMat[8] = src.mMat[6];
+        mMat[9] = src.mMat[7];
+        mMat[10] = src.mMat[8];
+        mMat[11] = 0;
+
+        mMat[12] = 0;
+        mMat[13] = 0;
+        mMat[14] = 0;
+        mMat[15] = 1;
+    }
+
+    /**
+    * Sets current values to be a rotation matrix of certain angle
+    * about a given axis
+    *
+    * @param rot angle of rotation
+    * @param x rotation axis x
+    * @param y rotation axis y
+    * @param z rotation axis z
+    */
+    public void loadRotate(float rot, float x, float y, float z) {
+        float c, s;
+        mMat[3] = 0;
+        mMat[7] = 0;
+        mMat[11]= 0;
+        mMat[12]= 0;
+        mMat[13]= 0;
+        mMat[14]= 0;
+        mMat[15]= 1;
+        rot *= (float)(java.lang.Math.PI / 180.0f);
+        c = (float)java.lang.Math.cos(rot);
+        s = (float)java.lang.Math.sin(rot);
+
+        float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
+        if (!(len != 1)) {
+            float recipLen = 1.f / len;
+            x *= recipLen;
+            y *= recipLen;
+            z *= recipLen;
+        }
+        float nc = 1.0f - c;
+        float xy = x * y;
+        float yz = y * z;
+        float zx = z * x;
+        float xs = x * s;
+        float ys = y * s;
+        float zs = z * s;
+        mMat[ 0] = x*x*nc +  c;
+        mMat[ 4] =  xy*nc - zs;
+        mMat[ 8] =  zx*nc + ys;
+        mMat[ 1] =  xy*nc + zs;
+        mMat[ 5] = y*y*nc +  c;
+        mMat[ 9] =  yz*nc - xs;
+        mMat[ 2] =  zx*nc - ys;
+        mMat[ 6] =  yz*nc + xs;
+        mMat[10] = z*z*nc +  c;
+    }
+
+    /**
+    * Sets current values to be a scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    * @param z scale component z
+    */
+    public void loadScale(float x, float y, float z) {
+        loadIdentity();
+        mMat[0] = x;
+        mMat[5] = y;
+        mMat[10] = z;
+    }
+
+    /**
+    * Sets current values to be a translation matrix of given
+    * dimensions
+    *
+    * @param x translation component x
+    * @param y translation component y
+    * @param z translation component z
+    */
+    public void loadTranslate(float x, float y, float z) {
+        loadIdentity();
+        mMat[12] = x;
+        mMat[13] = y;
+        mMat[14] = z;
+    }
+
+    /**
+    * Sets current values to be the result of multiplying two given
+    * matrices
+    *
+    * @param lhs left hand side matrix
+    * @param rhs right hand side matrix
+    */
+    public void loadMultiply(Matrix4f lhs, Matrix4f rhs) {
+        for (int i=0 ; i<4 ; i++) {
+            float ri0 = 0;
+            float ri1 = 0;
+            float ri2 = 0;
+            float ri3 = 0;
+            for (int j=0 ; j<4 ; j++) {
+                float rhs_ij = rhs.get(i,j);
+                ri0 += lhs.get(j,0) * rhs_ij;
+                ri1 += lhs.get(j,1) * rhs_ij;
+                ri2 += lhs.get(j,2) * rhs_ij;
+                ri3 += lhs.get(j,3) * rhs_ij;
+            }
+            set(i,0, ri0);
+            set(i,1, ri1);
+            set(i,2, ri2);
+            set(i,3, ri3);
+        }
+    }
+
+    /**
+    * Set current values to be an orthographic projection matrix
+    *
+    * @param l location of the left vertical clipping plane
+    * @param r location of the right vertical clipping plane
+    * @param b location of the bottom horizontal clipping plane
+    * @param t location of the top horizontal clipping plane
+    * @param n location of the near clipping plane
+    * @param f location of the far clipping plane
+    */
+    public void loadOrtho(float l, float r, float b, float t, float n, float f) {
+        loadIdentity();
+        mMat[0] = 2 / (r - l);
+        mMat[5] = 2 / (t - b);
+        mMat[10]= -2 / (f - n);
+        mMat[12]= -(r + l) / (r - l);
+        mMat[13]= -(t + b) / (t - b);
+        mMat[14]= -(f + n) / (f - n);
+    }
+
+    /**
+    * Set current values to be an orthographic projection matrix
+    * with the right and bottom clipping planes set to the given
+    * values. Left and top clipping planes are set to 0. Near and
+    * far are set to -1, 1 respectively
+    *
+    * @param w location of the right vertical clipping plane
+    * @param h location of the bottom horizontal clipping plane
+    *
+    */
+    public void loadOrthoWindow(int w, int h) {
+        loadOrtho(0,w, h,0, -1,1);
+    }
+
+    /**
+    * Sets current values to be a perspective projection matrix
+    *
+    * @param l location of the left vertical clipping plane
+    * @param r location of the right vertical clipping plane
+    * @param b location of the bottom horizontal clipping plane
+    * @param t location of the top horizontal clipping plane
+    * @param n location of the near clipping plane, must be positive
+    * @param f location of the far clipping plane, must be positive
+    *
+    */
+    public void loadFrustum(float l, float r, float b, float t, float n, float f) {
+        loadIdentity();
+        mMat[0] = 2 * n / (r - l);
+        mMat[5] = 2 * n / (t - b);
+        mMat[8] = (r + l) / (r - l);
+        mMat[9] = (t + b) / (t - b);
+        mMat[10]= -(f + n) / (f - n);
+        mMat[11]= -1;
+        mMat[14]= -2*f*n / (f - n);
+        mMat[15]= 0;
+    }
+
+    /**
+    * Sets current values to be a perspective projection matrix
+    *
+    * @param fovy vertical field of view angle in degrees
+    * @param aspect aspect ratio of the screen
+    * @param near near cliping plane, must be positive
+    * @param far far clipping plane, must be positive
+    */
+    public void loadPerspective(float fovy, float aspect, float near, float far) {
+        float top = near * (float)Math.tan((float) (fovy * Math.PI / 360.0f));
+        float bottom = -top;
+        float left = bottom * aspect;
+        float right = top * aspect;
+        loadFrustum(left, right, bottom, top, near, far);
+    }
+
+    /**
+    * Helper function to set the current values to a perspective
+    * projection matrix with aspect ratio defined by the parameters
+    * and (near, far), (bottom, top) mapping to (-1, 1) at z = 0
+    *
+    * @param w screen width
+    * @param h screen height
+    */
+    public void loadProjectionNormalized(int w, int h) {
+        // range -1,1 in the narrow axis at z = 0.
+        Matrix4f m1 = new Matrix4f();
+        Matrix4f m2 = new Matrix4f();
+
+        if(w > h) {
+            float aspect = ((float)w) / h;
+            m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
+        } else {
+            float aspect = ((float)h) / w;
+            m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
+        }
+
+        m2.loadRotate(180, 0, 1, 0);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadScale(-2, 2, 1);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadTranslate(0, 0, 2);
+        m1.loadMultiply(m1, m2);
+
+        load(m1);
+    }
+
+    /**
+    * Post-multiplies the current matrix by a given parameter
+    *
+    * @param rhs right hand side to multiply by
+    */
+    public void multiply(Matrix4f rhs) {
+        Matrix4f tmp = new Matrix4f();
+        tmp.loadMultiply(this, rhs);
+        load(tmp);
+    }
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * rotation matrix of certain angle about a given axis
+    *
+    * @param rot angle of rotation
+    * @param x rotation axis x
+    * @param y rotation axis y
+    * @param z rotation axis z
+    */
+    public void rotate(float rot, float x, float y, float z) {
+        Matrix4f tmp = new Matrix4f();
+        tmp.loadRotate(rot, x, y, z);
+        multiply(tmp);
+    }
+
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * scale matrix of given dimensions
+    *
+    * @param x scale component x
+    * @param y scale component y
+    * @param z scale component z
+    */
+    public void scale(float x, float y, float z) {
+        Matrix4f tmp = new Matrix4f();
+        tmp.loadScale(x, y, z);
+        multiply(tmp);
+    }
+
+    /**
+    * Modifies the current matrix by post-multiplying it with a
+    * translation matrix of given dimensions
+    *
+    * @param x translation component x
+    * @param y translation component y
+    * @param z translation component z
+    */
+    public void translate(float x, float y, float z) {
+        Matrix4f tmp = new Matrix4f();
+        tmp.loadTranslate(x, y, z);
+        multiply(tmp);
+    }
+    private float computeCofactor(int i, int j) {
+        int c0 = (i+1) % 4;
+        int c1 = (i+2) % 4;
+        int c2 = (i+3) % 4;
+        int r0 = (j+1) % 4;
+        int r1 = (j+2) % 4;
+        int r2 = (j+3) % 4;
+
+        float minor = (mMat[c0 + 4*r0] * (mMat[c1 + 4*r1] * mMat[c2 + 4*r2] -
+                                            mMat[c1 + 4*r2] * mMat[c2 + 4*r1]))
+                     - (mMat[c0 + 4*r1] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r2] -
+                                            mMat[c1 + 4*r2] * mMat[c2 + 4*r0]))
+                     + (mMat[c0 + 4*r2] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r1] -
+                                            mMat[c1 + 4*r1] * mMat[c2 + 4*r0]));
+
+        float cofactor = ((i+j) & 1) != 0 ? -minor : minor;
+        return cofactor;
+    }
+
+    /**
+    * Sets the current matrix to its inverse
+    */
+    public boolean inverse() {
+
+        Matrix4f result = new Matrix4f();
+
+        for (int i = 0; i < 4; ++i) {
+            for (int j = 0; j < 4; ++j) {
+                result.mMat[4*i + j] = computeCofactor(i, j);
+            }
+        }
+
+        // Dot product of 0th column of source and 0th row of result
+        float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[1] +
+                     mMat[8]*result.mMat[2] + mMat[12]*result.mMat[3];
+
+        if (Math.abs(det) < 1e-6) {
+            return false;
+        }
+
+        det = 1.0f / det;
+        for (int i = 0; i < 16; ++i) {
+            mMat[i] = result.mMat[i] * det;
+        }
+
+        return true;
+    }
+
+    /**
+    * Sets the current matrix to its inverse transpose
+    */
+    public boolean inverseTranspose() {
+
+        Matrix4f result = new Matrix4f();
+
+        for (int i = 0; i < 4; ++i) {
+            for (int j = 0; j < 4; ++j) {
+                result.mMat[4*j + i] = computeCofactor(i, j);
+            }
+        }
+
+        float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[4] +
+                     mMat[8]*result.mMat[8] + mMat[12]*result.mMat[12];
+
+        if (Math.abs(det) < 1e-6) {
+            return false;
+        }
+
+        det = 1.0f / det;
+        for (int i = 0; i < 16; ++i) {
+            mMat[i] = result.mMat[i] * det;
+        }
+
+        return true;
+    }
+
+    /**
+    * Sets the current matrix to its transpose
+    */
+    public void transpose() {
+        for(int i = 0; i < 3; ++i) {
+            for(int j = i + 1; j < 4; ++j) {
+                float temp = mMat[i*4 + j];
+                mMat[i*4 + j] = mMat[j*4 + i];
+                mMat[j*4 + i] = temp;
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+    final float[] mMat;
+}
diff --git a/android/renderscript/Mesh.java b/android/renderscript/Mesh.java
new file mode 100644
index 0000000..f2fd5a9
--- /dev/null
+++ b/android/renderscript/Mesh.java
@@ -0,0 +1,849 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
+
+import java.util.Vector;
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * <p>This class is a container for geometric data displayed with
+ * RenderScript. Internally, a mesh is a collection of allocations that
+ * represent vertex data (positions, normals, texture
+ * coordinates) and index data such as triangles and lines. </p>
+ * <p>
+ * Vertex data could either be interleaved within one
+ * allocation that is provided separately, as multiple allocation
+ * objects, or done as a combination of both. When a
+ * vertex channel name matches an input in the vertex program,
+ * RenderScript automatically connects the two together.
+ * </p>
+ * <p>
+ *  Parts of the mesh can be rendered with either explicit
+ *  index sets or primitive types.
+ * </p>
+ **/
+@Deprecated
+public class Mesh extends BaseObj {
+
+    /**
+    * @deprecated in API 16
+    * Describes the way mesh vertex data is interpreted when rendering
+    *
+    **/
+    public enum Primitive {
+        /**
+        * @deprecated in API 16
+        * Vertex data will be rendered as a series of points
+        */
+        @UnsupportedAppUsage
+        POINT (0),
+        /**
+        * @deprecated in API 16
+        * Vertex pairs will be rendered as lines
+        */
+        LINE (1),
+        /**
+        * @deprecated in API 16
+        * Vertex data will be rendered as a connected line strip
+        */
+        LINE_STRIP (2),
+        /**
+        * @deprecated in API 16
+        * Vertices will be rendered as individual triangles
+        */
+        @UnsupportedAppUsage
+        TRIANGLE (3),
+        /**
+        * @deprecated in API 16
+        * Vertices will be rendered as a connected triangle strip
+        * defined by the first three vertices with each additional
+        * triangle defined by a new vertex
+        */
+        TRIANGLE_STRIP (4),
+        /**
+        * @deprecated in API 16
+        * Vertices will be rendered as a sequence of triangles that all
+        * share first vertex as the origin
+        */
+        TRIANGLE_FAN (5);
+
+        int mID;
+        Primitive(int id) {
+            mID = id;
+        }
+    }
+
+    Allocation[] mVertexBuffers;
+    Allocation[] mIndexBuffers;
+    Primitive[] mPrimitives;
+
+    Mesh(long id, RenderScript rs) {
+        super(id, rs);
+        guard.open("destroy");
+    }
+
+    /**
+    * @deprecated in API 16
+    * @return number of allocations containing vertex data
+    *
+    **/
+    public int getVertexAllocationCount() {
+        if(mVertexBuffers == null) {
+            return 0;
+        }
+        return mVertexBuffers.length;
+    }
+    /**
+    * @deprecated in API 16
+    * @param slot index in the list of allocations to return
+    * @return vertex data allocation at the given index
+    *
+    **/
+    @UnsupportedAppUsage
+    public Allocation getVertexAllocation(int slot) {
+        return mVertexBuffers[slot];
+    }
+
+    /**
+    * @deprecated in API 16
+    * @return number of primitives or index sets in the mesh
+    *
+    **/
+    public int getPrimitiveCount() {
+        if(mIndexBuffers == null) {
+            return 0;
+        }
+        return mIndexBuffers.length;
+    }
+
+    /**
+    * @deprecated in API 16
+    * @param slot locaton within the list of index set allocation
+    * @return allocation containing primtive index data or null if
+    *         the index data is not specified explicitly
+    *
+    **/
+    public Allocation getIndexSetAllocation(int slot) {
+        return mIndexBuffers[slot];
+    }
+    /**
+    * @deprecated in API 16
+    * @param slot locaiton within the list of index set primitives
+    * @return index set primitive type
+    *
+    **/
+    public Primitive getPrimitive(int slot) {
+        return mPrimitives[slot];
+    }
+
+    @Override
+    void updateFromNative() {
+        super.updateFromNative();
+        int vtxCount = mRS.nMeshGetVertexBufferCount(getID(mRS));
+        int idxCount = mRS.nMeshGetIndexCount(getID(mRS));
+
+        long[] vtxIDs = new long[vtxCount];
+        long[] idxIDs = new long[idxCount];
+        int[] primitives = new int[idxCount];
+
+        mRS.nMeshGetVertices(getID(mRS), vtxIDs, vtxCount);
+        mRS.nMeshGetIndices(getID(mRS), idxIDs, primitives, idxCount);
+
+        mVertexBuffers = new Allocation[vtxCount];
+        mIndexBuffers = new Allocation[idxCount];
+        mPrimitives = new Primitive[idxCount];
+
+        for(int i = 0; i < vtxCount; i ++) {
+            if(vtxIDs[i] != 0) {
+                mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
+                mVertexBuffers[i].updateFromNative();
+            }
+        }
+
+        for(int i = 0; i < idxCount; i ++) {
+            if(idxIDs[i] != 0) {
+                mIndexBuffers[i] = new Allocation(idxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
+                mIndexBuffers[i].updateFromNative();
+            }
+            mPrimitives[i] = Primitive.values()[primitives[i]];
+        }
+    }
+
+    /**
+    * @deprecated in API 16
+    * Mesh builder object. It starts empty and requires you to
+    * add the types necessary to create vertex and index
+    * allocations.
+    *
+    */
+    public static class Builder {
+        RenderScript mRS;
+        int mUsage;
+
+        class Entry {
+            Type t;
+            Element e;
+            int size;
+            Primitive prim;
+            int usage;
+        }
+
+        int mVertexTypeCount;
+        Entry[] mVertexTypes;
+        Vector mIndexTypes;
+
+        /**
+        * @deprecated in API 16
+        * Creates builder object
+        * @param rs Context to which the mesh will belong.
+        * @param usage specifies how the mesh allocations are to be
+        *              handled, whether they need to be uploaded to a
+        *              buffer on the gpu, maintain a cpu copy, etc
+        */
+        public Builder(RenderScript rs, int usage) {
+            mRS = rs;
+            mUsage = usage;
+            mVertexTypeCount = 0;
+            mVertexTypes = new Entry[16];
+            mIndexTypes = new Vector();
+        }
+
+        /**
+        * @deprecated in API 16
+        * @return internal index of the last vertex buffer type added to
+        *         builder
+        **/
+        public int getCurrentVertexTypeIndex() {
+            return mVertexTypeCount - 1;
+        }
+
+        /**
+        * @deprecated in API 16
+        * @return internal index of the last index set added to the
+        *         builder
+        **/
+        public int getCurrentIndexSetIndex() {
+            return mIndexTypes.size() - 1;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds a vertex data type to the builder object
+        *
+        * @param t type of the vertex data allocation to be created
+        *
+        * @return this
+        **/
+        public Builder addVertexType(Type t) throws IllegalStateException {
+            if (mVertexTypeCount >= mVertexTypes.length) {
+                throw new IllegalStateException("Max vertex types exceeded.");
+            }
+
+            mVertexTypes[mVertexTypeCount] = new Entry();
+            mVertexTypes[mVertexTypeCount].t = t;
+            mVertexTypes[mVertexTypeCount].e = null;
+            mVertexTypeCount++;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds a vertex data type to the builder object
+        *
+        * @param e element describing the vertex data layout
+        * @param size number of elements in the buffer
+        *
+        * @return this
+        **/
+        public Builder addVertexType(Element e, int size) throws IllegalStateException {
+            if (mVertexTypeCount >= mVertexTypes.length) {
+                throw new IllegalStateException("Max vertex types exceeded.");
+            }
+
+            mVertexTypes[mVertexTypeCount] = new Entry();
+            mVertexTypes[mVertexTypeCount].t = null;
+            mVertexTypes[mVertexTypeCount].e = e;
+            mVertexTypes[mVertexTypeCount].size = size;
+            mVertexTypeCount++;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds an index set data type to the builder object
+        *
+        * @param t type of the index set data, could be null
+        * @param p primitive type
+        *
+        * @return this
+        **/
+        public Builder addIndexSetType(Type t, Primitive p) {
+            Entry indexType = new Entry();
+            indexType.t = t;
+            indexType.e = null;
+            indexType.size = 0;
+            indexType.prim = p;
+            mIndexTypes.addElement(indexType);
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds an index set primitive type to the builder object
+        *
+        * @param p primitive type
+        *
+        * @return this
+        **/
+        public Builder addIndexSetType(Primitive p) {
+            Entry indexType = new Entry();
+            indexType.t = null;
+            indexType.e = null;
+            indexType.size = 0;
+            indexType.prim = p;
+            mIndexTypes.addElement(indexType);
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds an index set data type to the builder object
+        *
+        * @param e element describing the index set data layout
+        * @param size number of elements in the buffer
+        * @param p primitive type
+        *
+        * @return this
+        **/
+        public Builder addIndexSetType(Element e, int size, Primitive p) {
+            Entry indexType = new Entry();
+            indexType.t = null;
+            indexType.e = e;
+            indexType.size = size;
+            indexType.prim = p;
+            mIndexTypes.addElement(indexType);
+            return this;
+        }
+
+        Type newType(Element e, int size) {
+            Type.Builder tb = new Type.Builder(mRS, e);
+            tb.setX(size);
+            return tb.create();
+        }
+
+        /**
+        * @deprecated in API 16
+        * Create a Mesh object from the current state of the builder
+        *
+        **/
+        public Mesh create() {
+            mRS.validate();
+            long[] vtx = new long[mVertexTypeCount];
+            long[] idx = new long[mIndexTypes.size()];
+            int[] prim = new int[mIndexTypes.size()];
+
+            Allocation[] vertexBuffers = new Allocation[mVertexTypeCount];
+            Allocation[] indexBuffers = new Allocation[mIndexTypes.size()];
+            Primitive[] primitives = new Primitive[mIndexTypes.size()];
+
+            for(int ct = 0; ct < mVertexTypeCount; ct ++) {
+                Allocation alloc = null;
+                Entry entry = mVertexTypes[ct];
+                if (entry.t != null) {
+                    alloc = Allocation.createTyped(mRS, entry.t, mUsage);
+                } else if(entry.e != null) {
+                    alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
+                } else {
+                    // Should never happen because the builder will always set one
+                    throw new IllegalStateException("Builder corrupt, no valid element in entry.");
+                }
+                vertexBuffers[ct] = alloc;
+                vtx[ct] = alloc.getID(mRS);
+            }
+
+            for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
+                Allocation alloc = null;
+                Entry entry = (Entry)mIndexTypes.elementAt(ct);
+                if (entry.t != null) {
+                    alloc = Allocation.createTyped(mRS, entry.t, mUsage);
+                } else if(entry.e != null) {
+                    alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
+                } else {
+                    // Should never happen because the builder will always set one
+                    throw new IllegalStateException("Builder corrupt, no valid element in entry.");
+                }
+                long allocID = (alloc == null) ? 0 : alloc.getID(mRS);
+                indexBuffers[ct] = alloc;
+                primitives[ct] = entry.prim;
+
+                idx[ct] = allocID;
+                prim[ct] = entry.prim.mID;
+            }
+
+            long id = mRS.nMeshCreate(vtx, idx, prim);
+            Mesh newMesh = new Mesh(id, mRS);
+            newMesh.mVertexBuffers = vertexBuffers;
+            newMesh.mIndexBuffers = indexBuffers;
+            newMesh.mPrimitives = primitives;
+
+            return newMesh;
+        }
+    }
+
+    /**
+    * @deprecated in API 16
+    * Mesh builder object. It starts empty and requires the user to
+    * add all the vertex and index allocations that comprise the
+    * mesh
+    *
+    */
+    public static class AllocationBuilder {
+        RenderScript mRS;
+
+        class Entry {
+            Allocation a;
+            Primitive prim;
+        }
+
+        int mVertexTypeCount;
+        Entry[] mVertexTypes;
+
+        Vector mIndexTypes;
+
+        /**
+        * @deprecated in API 16
+        **/
+        @UnsupportedAppUsage
+        public AllocationBuilder(RenderScript rs) {
+            mRS = rs;
+            mVertexTypeCount = 0;
+            mVertexTypes = new Entry[16];
+            mIndexTypes = new Vector();
+        }
+
+        /**
+        * @deprecated in API 16
+        * @return internal index of the last vertex buffer type added to
+        *         builder
+        **/
+        public int getCurrentVertexTypeIndex() {
+            return mVertexTypeCount - 1;
+        }
+
+        /**
+        * @deprecated in API 16
+        * @return internal index of the last index set added to the
+        *         builder
+        **/
+        public int getCurrentIndexSetIndex() {
+            return mIndexTypes.size() - 1;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds an allocation containing vertex buffer data to the
+        * builder
+        *
+        * @param a vertex data allocation
+        *
+        * @return this
+        **/
+        @UnsupportedAppUsage
+        public AllocationBuilder addVertexAllocation(Allocation a) throws IllegalStateException {
+            if (mVertexTypeCount >= mVertexTypes.length) {
+                throw new IllegalStateException("Max vertex types exceeded.");
+            }
+
+            mVertexTypes[mVertexTypeCount] = new Entry();
+            mVertexTypes[mVertexTypeCount].a = a;
+            mVertexTypeCount++;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds an allocation containing index buffer data and index type
+        * to the builder
+        *
+        * @param a index set data allocation, could be null
+        * @param p index set primitive type
+        *
+        * @return this
+        **/
+        @UnsupportedAppUsage
+        public AllocationBuilder addIndexSetAllocation(Allocation a, Primitive p) {
+            Entry indexType = new Entry();
+            indexType.a = a;
+            indexType.prim = p;
+            mIndexTypes.addElement(indexType);
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds an index set type to the builder
+        *
+        * @param p index set primitive type
+        *
+        * @return this
+        **/
+        @UnsupportedAppUsage
+        public AllocationBuilder addIndexSetType(Primitive p) {
+            Entry indexType = new Entry();
+            indexType.a = null;
+            indexType.prim = p;
+            mIndexTypes.addElement(indexType);
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Create a Mesh object from the current state of the builder
+        *
+        **/
+        @UnsupportedAppUsage
+        public Mesh create() {
+            mRS.validate();
+
+            long[] vtx = new long[mVertexTypeCount];
+            long[] idx = new long[mIndexTypes.size()];
+            int[] prim = new int[mIndexTypes.size()];
+
+            Allocation[] indexBuffers = new Allocation[mIndexTypes.size()];
+            Primitive[] primitives = new Primitive[mIndexTypes.size()];
+            Allocation[] vertexBuffers = new Allocation[mVertexTypeCount];
+
+            for(int ct = 0; ct < mVertexTypeCount; ct ++) {
+                Entry entry = mVertexTypes[ct];
+                vertexBuffers[ct] = entry.a;
+                vtx[ct] = entry.a.getID(mRS);
+            }
+
+            for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
+                Entry entry = (Entry)mIndexTypes.elementAt(ct);
+                long allocID = (entry.a == null) ? 0 : entry.a.getID(mRS);
+                indexBuffers[ct] = entry.a;
+                primitives[ct] = entry.prim;
+
+                idx[ct] = allocID;
+                prim[ct] = entry.prim.mID;
+            }
+
+            long id = mRS.nMeshCreate(vtx, idx, prim);
+            Mesh newMesh = new Mesh(id, mRS);
+            newMesh.mVertexBuffers = vertexBuffers;
+            newMesh.mIndexBuffers = indexBuffers;
+            newMesh.mPrimitives = primitives;
+
+            return newMesh;
+        }
+    }
+
+    /**
+    * @deprecated in API 16
+    * Builder that allows creation of a mesh object point by point
+    * and triangle by triangle
+    *
+    **/
+    public static class TriangleMeshBuilder {
+        float mVtxData[];
+        int mVtxCount;
+        int mMaxIndex;
+        short mIndexData[];
+        int mIndexCount;
+        RenderScript mRS;
+        Element mElement;
+
+        float mNX = 0;
+        float mNY = 0;
+        float mNZ = -1;
+        float mS0 = 0;
+        float mT0 = 0;
+        float mR = 1;
+        float mG = 1;
+        float mB = 1;
+        float mA = 1;
+
+        int mVtxSize;
+        int mFlags;
+
+        /**
+        * @deprecated in API 16
+        **/
+        public static final int COLOR = 0x0001;
+        /**
+        * @deprecated in API 16
+        **/
+        public static final int NORMAL = 0x0002;
+        /**
+        * @deprecated in API 16
+        **/
+        public static final int TEXTURE_0 = 0x0100;
+
+        /**
+        * @deprecated in API 16
+        * @param rs Context to which the mesh will belong.
+        * @param vtxSize specifies whether the vertex is a float2 or
+        *                float3
+        * @param flags bitfield that is a combination of COLOR, NORMAL,
+        *              and TEXTURE_0 that specifies what vertex data
+        *              channels are present in the mesh
+        *
+        **/
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
+            mRS = rs;
+            mVtxCount = 0;
+            mMaxIndex = 0;
+            mIndexCount = 0;
+            mVtxData = new float[128];
+            mIndexData = new short[128];
+            mVtxSize = vtxSize;
+            mFlags = flags;
+
+            if (vtxSize < 2 || vtxSize > 3) {
+                throw new IllegalArgumentException("Vertex size out of range.");
+            }
+        }
+
+        private void makeSpace(int count) {
+            if ((mVtxCount + count) >= mVtxData.length) {
+                float t[] = new float[mVtxData.length * 2];
+                System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
+                mVtxData = t;
+            }
+        }
+
+        private void latch() {
+            if ((mFlags & COLOR) != 0) {
+                makeSpace(4);
+                mVtxData[mVtxCount++] = mR;
+                mVtxData[mVtxCount++] = mG;
+                mVtxData[mVtxCount++] = mB;
+                mVtxData[mVtxCount++] = mA;
+            }
+            if ((mFlags & TEXTURE_0) != 0) {
+                makeSpace(2);
+                mVtxData[mVtxCount++] = mS0;
+                mVtxData[mVtxCount++] = mT0;
+            }
+            if ((mFlags & NORMAL) != 0) {
+                makeSpace(4);
+                mVtxData[mVtxCount++] = mNX;
+                mVtxData[mVtxCount++] = mNY;
+                mVtxData[mVtxCount++] = mNZ;
+                mVtxData[mVtxCount++] = 0.0f;
+            }
+            mMaxIndex ++;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds a float2 vertex to the mesh
+        *
+        * @param x position x
+        * @param y position y
+        *
+        * @return this
+        *
+        **/
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public TriangleMeshBuilder addVertex(float x, float y) {
+            if (mVtxSize != 2) {
+                throw new IllegalStateException("add mistmatch with declared components.");
+            }
+            makeSpace(2);
+            mVtxData[mVtxCount++] = x;
+            mVtxData[mVtxCount++] = y;
+            latch();
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds a float3 vertex to the mesh
+        *
+        * @param x position x
+        * @param y position y
+        * @param z position z
+        *
+        * @return this
+        *
+        **/
+        public TriangleMeshBuilder addVertex(float x, float y, float z) {
+            if (mVtxSize != 3) {
+                throw new IllegalStateException("add mistmatch with declared components.");
+            }
+            makeSpace(4);
+            mVtxData[mVtxCount++] = x;
+            mVtxData[mVtxCount++] = y;
+            mVtxData[mVtxCount++] = z;
+            mVtxData[mVtxCount++] = 1.0f;
+            latch();
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Sets the texture coordinate for the vertices that are added after this method call.
+        *
+        * @param s texture coordinate s
+        * @param t texture coordinate t
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder setTexture(float s, float t) {
+            if ((mFlags & TEXTURE_0) == 0) {
+                throw new IllegalStateException("add mistmatch with declared components.");
+            }
+            mS0 = s;
+            mT0 = t;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Sets the normal vector for the vertices that are added after this method call.
+        *
+        * @param x normal vector x
+        * @param y normal vector y
+        * @param z normal vector z
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder setNormal(float x, float y, float z) {
+            if ((mFlags & NORMAL) == 0) {
+                throw new IllegalStateException("add mistmatch with declared components.");
+            }
+            mNX = x;
+            mNY = y;
+            mNZ = z;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Sets the color for the vertices that are added after this method call.
+        *
+        * @param r red component
+        * @param g green component
+        * @param b blue component
+        * @param a alpha component
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder setColor(float r, float g, float b, float a) {
+            if ((mFlags & COLOR) == 0) {
+                throw new IllegalStateException("add mistmatch with declared components.");
+            }
+            mR = r;
+            mG = g;
+            mB = b;
+            mA = a;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Adds a new triangle to the mesh builder
+        *
+        * @param idx1 index of the first vertex in the triangle
+        * @param idx2 index of the second vertex in the triangle
+        * @param idx3 index of the third vertex in the triangle
+        *
+        * @return this
+        **/
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public TriangleMeshBuilder addTriangle(int idx1, int idx2, int idx3) {
+            if((idx1 >= mMaxIndex) || (idx1 < 0) ||
+               (idx2 >= mMaxIndex) || (idx2 < 0) ||
+               (idx3 >= mMaxIndex) || (idx3 < 0)) {
+               throw new IllegalStateException("Index provided greater than vertex count.");
+            }
+            if ((mIndexCount + 3) >= mIndexData.length) {
+                short t[] = new short[mIndexData.length * 2];
+                System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
+                mIndexData = t;
+            }
+            mIndexData[mIndexCount++] = (short)idx1;
+            mIndexData[mIndexCount++] = (short)idx2;
+            mIndexData[mIndexCount++] = (short)idx3;
+            return this;
+        }
+
+        /**
+        * @deprecated in API 16
+        * Creates the mesh object from the current state of the builder
+        *
+        * @param uploadToBufferObject specifies whether the vertex data
+        *                             is to be uploaded into the buffer
+        *                             object indicating that it's likely
+        *                             not going to be modified and
+        *                             rendered many times.
+        *                             Alternatively, it indicates the
+        *                             mesh data will be updated
+        *                             frequently and remain in script
+        *                             accessible memory
+        *
+        **/
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public Mesh create(boolean uploadToBufferObject) {
+            Element.Builder b = new Element.Builder(mRS);
+            b.add(Element.createVector(mRS,
+                                       Element.DataType.FLOAT_32,
+                                       mVtxSize), "position");
+            if ((mFlags & COLOR) != 0) {
+                b.add(Element.F32_4(mRS), "color");
+            }
+            if ((mFlags & TEXTURE_0) != 0) {
+                b.add(Element.F32_2(mRS), "texture0");
+            }
+            if ((mFlags & NORMAL) != 0) {
+                b.add(Element.F32_3(mRS), "normal");
+            }
+            mElement = b.create();
+
+            int usage = Allocation.USAGE_SCRIPT;
+            if (uploadToBufferObject) {
+                usage |= Allocation.USAGE_GRAPHICS_VERTEX;
+            }
+
+            Builder smb = new Builder(mRS, usage);
+            smb.addVertexType(mElement, mMaxIndex);
+            smb.addIndexSetType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
+
+            Mesh sm = smb.create();
+
+            sm.getVertexAllocation(0).copy1DRangeFromUnchecked(0, mMaxIndex, mVtxData);
+            if(uploadToBufferObject) {
+                sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
+            }
+
+            sm.getIndexSetAllocation(0).copy1DRangeFromUnchecked(0, mIndexCount, mIndexData);
+            if (uploadToBufferObject) {
+                sm.getIndexSetAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
+            }
+
+            return sm;
+        }
+    }
+}
+
diff --git a/android/renderscript/Program.java b/android/renderscript/Program.java
new file mode 100644
index 0000000..3cadc93
--- /dev/null
+++ b/android/renderscript/Program.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * @hide
+ *
+ * Program is a base class for all the objects that modify
+ * various stages of the graphics pipeline
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Program extends BaseObj {
+    static final int MAX_INPUT = 8;
+    static final int MAX_OUTPUT = 8;
+    static final int MAX_CONSTANT = 8;
+    static final int MAX_TEXTURE = 8;
+
+    /**
+     *
+     * TextureType specifies what textures are attached to Program
+     * objects
+     *
+     **/
+    public enum TextureType {
+        @UnsupportedAppUsage
+        TEXTURE_2D (0),
+        TEXTURE_CUBE (1);
+
+        int mID;
+        TextureType(int id) {
+            mID = id;
+        }
+    }
+
+    enum ProgramParam {
+        INPUT (0),
+        OUTPUT (1),
+        CONSTANT (2),
+        TEXTURE_TYPE (3);
+
+        int mID;
+        ProgramParam(int id) {
+            mID = id;
+        }
+    };
+
+    Element mInputs[];
+    Element mOutputs[];
+    Type mConstants[];
+    TextureType mTextures[];
+    String mTextureNames[];
+    int mTextureCount;
+    String mShader;
+
+    Program(long id, RenderScript rs) {
+        super(id, rs);
+        guard.open("destroy");
+    }
+
+    /**
+     * Program object can have zero or more constant allocations
+     * associated with it. This method returns the total count.
+     * @return number of constant input types
+     */
+    public int getConstantCount() {
+        return mConstants != null ? mConstants.length : 0;
+    }
+
+    /**
+     * Returns the type of the constant buffer used in the program
+     * object. It could be used to query internal elements or create
+     * an allocation to store constant data.
+     * @param slot index of the constant input type to return
+     * @return constant input type
+     */
+    public Type getConstant(int slot) {
+        if (slot < 0 || slot >= mConstants.length) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        return mConstants[slot];
+    }
+
+    /**
+     * Returns the number of textures used in this program object
+     * @return number of texture inputs
+     */
+    public int getTextureCount() {
+        return mTextureCount;
+    }
+
+    /**
+     * Returns the type of texture at a given slot. e.g. 2D or Cube
+     * @param slot index of the texture input
+     * @return texture input type
+     */
+    public TextureType getTextureType(int slot) {
+        if ((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        return mTextures[slot];
+    }
+
+    /**
+     * Returns the name of the texture input at a given slot. e.g.
+     * tex0, diffuse, spec
+     * @param slot index of the texture input
+     * @return texture input name
+     */
+    public String getTextureName(int slot) {
+        if ((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        return mTextureNames[slot];
+    }
+
+    /**
+     * Binds a constant buffer to be used as uniform inputs to the
+     * program
+     *
+     * @param a allocation containing uniform data
+     * @param slot index within the program's list of constant
+     *             buffer allocations
+     */
+    public void bindConstants(Allocation a, int slot) {
+        if (slot < 0 || slot >= mConstants.length) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        if (a != null &&
+            a.getType().getID(mRS) != mConstants[slot].getID(mRS)) {
+            throw new IllegalArgumentException("Allocation type does not match slot type.");
+        }
+        long id = a != null ? a.getID(mRS) : 0;
+        mRS.nProgramBindConstants(getID(mRS), slot, id);
+    }
+
+    /**
+     * Binds a texture to be used in the program
+     *
+     * @param va allocation containing texture data
+     * @param slot index within the program's list of textures
+     *
+     */
+    public void bindTexture(Allocation va, int slot)
+        throws IllegalArgumentException {
+        mRS.validate();
+        if ((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        if (va != null && va.getType().hasFaces() &&
+            mTextures[slot] != TextureType.TEXTURE_CUBE) {
+            throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot");
+        }
+
+        long id = va != null ? va.getID(mRS) : 0;
+        mRS.nProgramBindTexture(getID(mRS), slot, id);
+    }
+
+    /**
+     * Binds an object that describes how a texture at the
+     * corresponding location is sampled
+     *
+     * @param vs sampler for a corresponding texture
+     * @param slot index within the program's list of textures to
+     *             use the sampler on
+     *
+     */
+    public void bindSampler(Sampler vs, int slot)
+        throws IllegalArgumentException {
+        mRS.validate();
+        if ((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+
+        long id = vs != null ? vs.getID(mRS) : 0;
+        mRS.nProgramBindSampler(getID(mRS), slot, id);
+    }
+
+
+    public static class BaseProgramBuilder {
+        @UnsupportedAppUsage
+        RenderScript mRS;
+        @UnsupportedAppUsage
+        Element mInputs[];
+        @UnsupportedAppUsage
+        Element mOutputs[];
+        @UnsupportedAppUsage
+        Type mConstants[];
+        Type mTextures[];
+        TextureType mTextureTypes[];
+        String mTextureNames[];
+        @UnsupportedAppUsage
+        int mInputCount;
+        @UnsupportedAppUsage
+        int mOutputCount;
+        @UnsupportedAppUsage
+        int mConstantCount;
+        @UnsupportedAppUsage
+        int mTextureCount;
+        @UnsupportedAppUsage
+        String mShader;
+
+
+        @UnsupportedAppUsage
+        protected BaseProgramBuilder(RenderScript rs) {
+            mRS = rs;
+            mInputs = new Element[MAX_INPUT];
+            mOutputs = new Element[MAX_OUTPUT];
+            mConstants = new Type[MAX_CONSTANT];
+            mInputCount = 0;
+            mOutputCount = 0;
+            mConstantCount = 0;
+            mTextureCount = 0;
+            mTextureTypes = new TextureType[MAX_TEXTURE];
+            mTextureNames = new String[MAX_TEXTURE];
+        }
+
+        /**
+         * Sets the GLSL shader code to be used in the program
+         *
+         * @param s GLSL shader string
+         * @return  self
+         */
+        public BaseProgramBuilder setShader(String s) {
+            mShader = s;
+            return this;
+        }
+
+        /**
+         * Sets the GLSL shader code to be used in the program
+         *
+         * @param resources application resources
+         * @param resourceID id of the file containing GLSL shader code
+         *
+         * @return  self
+         */
+        public BaseProgramBuilder setShader(Resources resources, int resourceID) {
+            byte[] str;
+            int strLength;
+            InputStream is = resources.openRawResource(resourceID);
+            try {
+                try {
+                    str = new byte[1024];
+                    strLength = 0;
+                    while(true) {
+                        int bytesLeft = str.length - strLength;
+                        if (bytesLeft == 0) {
+                            byte[] buf2 = new byte[str.length * 2];
+                            System.arraycopy(str, 0, buf2, 0, str.length);
+                            str = buf2;
+                            bytesLeft = str.length - strLength;
+                        }
+                        int bytesRead = is.read(str, strLength, bytesLeft);
+                        if (bytesRead <= 0) {
+                            break;
+                        }
+                        strLength += bytesRead;
+                    }
+                } finally {
+                    is.close();
+                }
+            } catch(IOException e) {
+                throw new Resources.NotFoundException();
+            }
+
+            try {
+                mShader = new String(str, 0, strLength, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                Log.e("RenderScript shader creation", "Could not decode shader string");
+            }
+
+            return this;
+        }
+
+        /**
+         * Queries the index of the last added constant buffer type
+         *
+         */
+        public int getCurrentConstantIndex() {
+            return mConstantCount - 1;
+        }
+
+        /**
+         * Queries the index of the last added texture type
+         *
+         */
+        public int getCurrentTextureIndex() {
+            return mTextureCount - 1;
+        }
+
+        /**
+         * Adds constant (uniform) inputs to the program
+         *
+         * @param t Type that describes the layout of the Allocation
+         *          object to be used as constant inputs to the Program
+         * @return  self
+         */
+        public BaseProgramBuilder addConstant(Type t) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mConstantCount >= MAX_CONSTANT) {
+                throw new RSIllegalArgumentException("Max input count exceeded.");
+            }
+            if (t.getElement().isComplex()) {
+                throw new RSIllegalArgumentException("Complex elements not allowed.");
+            }
+            mConstants[mConstantCount] = t;
+            mConstantCount++;
+            return this;
+        }
+
+        /**
+         * Adds a texture input to the Program
+         *
+         * @param texType describes that the texture to append it (2D,
+         *                Cubemap, etc.)
+         * @return  self
+         */
+        public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException {
+            addTexture(texType, "Tex" + mTextureCount);
+            return this;
+        }
+
+        /**
+         * Adds a texture input to the Program
+         *
+         * @param texType describes that the texture to append it (2D,
+         *                Cubemap, etc.)
+         * @param texName what the texture should be called in the
+         *                shader
+         * @return  self
+         */
+        public BaseProgramBuilder addTexture(TextureType texType, String texName)
+            throws IllegalArgumentException {
+            if(mTextureCount >= MAX_TEXTURE) {
+                throw new IllegalArgumentException("Max texture count exceeded.");
+            }
+            mTextureTypes[mTextureCount] = texType;
+            mTextureNames[mTextureCount] = texName;
+            mTextureCount ++;
+            return this;
+        }
+
+        protected void initProgram(Program p) {
+            p.mInputs = new Element[mInputCount];
+            System.arraycopy(mInputs, 0, p.mInputs, 0, mInputCount);
+            p.mOutputs = new Element[mOutputCount];
+            System.arraycopy(mOutputs, 0, p.mOutputs, 0, mOutputCount);
+            p.mConstants = new Type[mConstantCount];
+            System.arraycopy(mConstants, 0, p.mConstants, 0, mConstantCount);
+            p.mTextureCount = mTextureCount;
+            p.mTextures = new TextureType[mTextureCount];
+            System.arraycopy(mTextureTypes, 0, p.mTextures, 0, mTextureCount);
+            p.mTextureNames = new String[mTextureCount];
+            System.arraycopy(mTextureNames, 0, p.mTextureNames, 0, mTextureCount);
+        }
+    }
+
+}
+
+
diff --git a/android/renderscript/ProgramFragment.java b/android/renderscript/ProgramFragment.java
new file mode 100644
index 0000000..e2879d8
--- /dev/null
+++ b/android/renderscript/ProgramFragment.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * <p>The RenderScript fragment program, also known as fragment shader is responsible
+ * for manipulating pixel data in a user defined way. It's constructed from a GLSL
+ * shader string containing the program body, textures inputs, and a Type object
+ * that describes the constants used by the program. Similar to the vertex programs,
+ * when an allocation with constant input values is bound to the shader, its values
+ * are sent to the graphics program automatically.</p>
+ * <p> The values inside the allocation are not explicitly tracked. If they change between two draw
+ * calls using the same program object, the runtime needs to be notified of that
+ * change by calling rsgAllocationSyncAll so it could send the new values to hardware.
+ * Communication between the vertex and fragment programs is handled internally in the
+ * GLSL code. For example, if the fragment program is expecting a varying input called
+ * varTex0, the GLSL code inside the program vertex must provide it.
+ * </p>
+ *
+ **/
+@Deprecated
+public class ProgramFragment extends Program {
+    ProgramFragment(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static class Builder extends BaseProgramBuilder {
+        /**
+         * @deprecated in API 16
+         * Create a builder object.
+         *
+         * @param rs Context to which the program will belong.
+         */
+        @UnsupportedAppUsage
+        public Builder(RenderScript rs) {
+            super(rs);
+        }
+
+        /**
+         * @deprecated in API 16
+         * Creates ProgramFragment from the current state of the builder
+         *
+         * @return  ProgramFragment
+         */
+        @UnsupportedAppUsage
+        public ProgramFragment create() {
+            mRS.validate();
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = ProgramParam.INPUT.mID;
+                tmp[idx++] = mInputs[i].getID(mRS);
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = ProgramParam.OUTPUT.mID;
+                tmp[idx++] = mOutputs[i].getID(mRS);
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = ProgramParam.CONSTANT.mID;
+                tmp[idx++] = mConstants[i].getID(mRS);
+            }
+            for (int i=0; i < mTextureCount; i++) {
+                tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
+                tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
+            }
+
+            long id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
+            ProgramFragment pf = new ProgramFragment(id, mRS);
+            initProgram(pf);
+            return pf;
+        }
+    }
+}
+
+
+
diff --git a/android/renderscript/ProgramFragmentFixedFunction.java b/android/renderscript/ProgramFragmentFixedFunction.java
new file mode 100644
index 0000000..8dbf6f4
--- /dev/null
+++ b/android/renderscript/ProgramFragmentFixedFunction.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * <p>ProgramFragmentFixedFunction is a helper class that provides
+ * a way to make a simple fragment shader without writing any
+ * GLSL code. This class allows for display of constant color, interpolated
+ * color from the vertex shader, or combinations of the both
+ * blended with results of up to two texture lookups.</p
+ *
+ **/
+@Deprecated
+public class ProgramFragmentFixedFunction extends ProgramFragment {
+    ProgramFragmentFixedFunction(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    static class InternalBuilder extends BaseProgramBuilder {
+        /**
+         * @deprecated in API 16
+         */
+        public InternalBuilder(RenderScript rs) {
+            super(rs);
+        }
+
+        /**
+         * @deprecated in API 16
+         * Creates ProgramFragmentFixedFunction from the current state
+         * of the builder
+         *
+         * @return  ProgramFragmentFixedFunction
+         */
+        public ProgramFragmentFixedFunction create() {
+            mRS.validate();
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = ProgramParam.INPUT.mID;
+                tmp[idx++] = mInputs[i].getID(mRS);
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = ProgramParam.OUTPUT.mID;
+                tmp[idx++] = mOutputs[i].getID(mRS);
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = ProgramParam.CONSTANT.mID;
+                tmp[idx++] = mConstants[i].getID(mRS);
+            }
+            for (int i=0; i < mTextureCount; i++) {
+                tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
+                tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
+            }
+
+            long id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
+            ProgramFragmentFixedFunction pf = new ProgramFragmentFixedFunction(id, mRS);
+            initProgram(pf);
+            return pf;
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static class Builder {
+        /**
+         * @deprecated in API 16
+         */
+        public static final int MAX_TEXTURE = 2;
+        int mNumTextures;
+        boolean mPointSpriteEnable;
+        boolean mVaryingColorEnable;
+        String mShader;
+        RenderScript mRS;
+
+        /**
+         * @deprecated in API 16
+         * EnvMode describes how textures are combined with the existing
+         * color in the fixed function fragment shader
+         *
+         **/
+        public enum EnvMode {
+            /**
+             * @deprecated in API 16
+             **/
+            @UnsupportedAppUsage
+            REPLACE (1),
+            /**
+             * @deprecated in API 16
+             **/
+            @UnsupportedAppUsage
+            MODULATE (2),
+            /**
+             * @deprecated in API 16
+             **/
+            DECAL (3);
+
+            int mID;
+            EnvMode(int id) {
+                mID = id;
+            }
+        }
+
+        /**
+         * @deprecated in API 16
+         * Format describes the pixel format of textures in the fixed
+         * function fragment shader and how they are sampled
+         *
+         **/
+        public enum Format {
+            /**
+             * @deprecated in API 16
+             **/
+            @UnsupportedAppUsage
+            ALPHA (1),
+            /**
+             * @deprecated in API 16
+             **/
+            LUMINANCE_ALPHA (2),
+            /**
+             * @deprecated in API 16
+             **/
+            @UnsupportedAppUsage
+            RGB (3),
+            /**
+             * @deprecated in API 16
+             **/
+            @UnsupportedAppUsage
+            RGBA (4);
+
+            int mID;
+            Format(int id) {
+                mID = id;
+            }
+        }
+
+        private class Slot {
+            EnvMode env;
+            Format format;
+            Slot(EnvMode _env, Format _fmt) {
+                env = _env;
+                format = _fmt;
+            }
+        }
+        Slot[] mSlots;
+
+        private void buildShaderString() {
+            mShader  = "//rs_shader_internal\n";
+            mShader += "varying lowp vec4 varColor;\n";
+            mShader += "varying vec2 varTex0;\n";
+
+            mShader += "void main() {\n";
+            if (mVaryingColorEnable) {
+                mShader += "  lowp vec4 col = varColor;\n";
+            } else {
+                mShader += "  lowp vec4 col = UNI_Color;\n";
+            }
+
+            if (mNumTextures != 0) {
+                if (mPointSpriteEnable) {
+                    mShader += "  vec2 t0 = gl_PointCoord;\n";
+                } else {
+                    mShader += "  vec2 t0 = varTex0.xy;\n";
+                }
+            }
+
+            for(int i = 0; i < mNumTextures; i ++) {
+                switch(mSlots[i].env) {
+                case REPLACE:
+                    switch (mSlots[i].format) {
+                    case ALPHA:
+                        mShader += "  col.a = texture2D(UNI_Tex0, t0).a;\n";
+                        break;
+                    case LUMINANCE_ALPHA:
+                        mShader += "  col.rgba = texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    case RGB:
+                        mShader += "  col.rgb = texture2D(UNI_Tex0, t0).rgb;\n";
+                        break;
+                    case RGBA:
+                        mShader += "  col.rgba = texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    }
+                    break;
+                case MODULATE:
+                    switch (mSlots[i].format) {
+                    case ALPHA:
+                        mShader += "  col.a *= texture2D(UNI_Tex0, t0).a;\n";
+                        break;
+                    case LUMINANCE_ALPHA:
+                        mShader += "  col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    case RGB:
+                        mShader += "  col.rgb *= texture2D(UNI_Tex0, t0).rgb;\n";
+                        break;
+                    case RGBA:
+                        mShader += "  col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    }
+                    break;
+                case DECAL:
+                    mShader += "  col = texture2D(UNI_Tex0, t0);\n";
+                    break;
+                }
+            }
+
+            mShader += "  gl_FragColor = col;\n";
+            mShader += "}\n";
+        }
+
+        /**
+         * @deprecated
+         * Creates a builder for fixed function fragment program
+         *
+         * @param rs Context to which the program will belong.
+         */
+        @UnsupportedAppUsage
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mSlots = new Slot[MAX_TEXTURE];
+            mPointSpriteEnable = false;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Adds a texture to be fetched as part of the fixed function
+         * fragment program
+         *
+         * @param env specifies how the texture is combined with the
+         *            current color
+         * @param fmt specifies the format of the texture and how its
+         *            components will be used to combine with the
+         *            current color
+         * @param slot index of the texture to apply the operations on
+         *
+         * @return this
+         */
+        @UnsupportedAppUsage
+        public Builder setTexture(EnvMode env, Format fmt, int slot)
+            throws IllegalArgumentException {
+            if((slot < 0) || (slot >= MAX_TEXTURE)) {
+                throw new IllegalArgumentException("MAX_TEXTURE exceeded.");
+            }
+            mSlots[slot] = new Slot(env, fmt);
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Specifies whether the texture coordinate passed from the
+         * vertex program is replaced with an openGL internal point
+         * sprite texture coordinate
+         *
+         **/
+        public Builder setPointSpriteTexCoordinateReplacement(boolean enable) {
+            mPointSpriteEnable = enable;
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Specifies whether the varying color passed from the vertex
+         * program or the constant color set on the fragment program is
+         * used in the final color calculation in the fixed function
+         * fragment shader
+         *
+         **/
+        @UnsupportedAppUsage
+        public Builder setVaryingColor(boolean enable) {
+            mVaryingColorEnable = enable;
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+        * Creates the fixed function fragment program from the current
+        * state of the builder.
+        *
+        */
+        @UnsupportedAppUsage
+        public ProgramFragmentFixedFunction create() {
+            InternalBuilder sb = new InternalBuilder(mRS);
+            mNumTextures = 0;
+            for(int i = 0; i < MAX_TEXTURE; i ++) {
+                if(mSlots[i] != null) {
+                    mNumTextures ++;
+                }
+            }
+            buildShaderString();
+            sb.setShader(mShader);
+
+            Type constType = null;
+            if (!mVaryingColorEnable) {
+                Element.Builder b = new Element.Builder(mRS);
+                b.add(Element.F32_4(mRS), "Color");
+                Type.Builder typeBuilder = new Type.Builder(mRS, b.create());
+                typeBuilder.setX(1);
+                constType = typeBuilder.create();
+                sb.addConstant(constType);
+            }
+            for (int i = 0; i < mNumTextures; i ++) {
+                sb.addTexture(TextureType.TEXTURE_2D);
+            }
+
+            ProgramFragmentFixedFunction pf = sb.create();
+            pf.mTextureCount = MAX_TEXTURE;
+            if (!mVaryingColorEnable) {
+                Allocation constantData = Allocation.createTyped(mRS,constType);
+                FieldPacker fp = new FieldPacker(16);
+                Float4 f4 = new Float4(1.f, 1.f, 1.f, 1.f);
+                fp.addF32(f4);
+                constantData.setFromFieldPacker(0, fp);
+                pf.bindConstants(constantData, 0);
+            }
+            return pf;
+        }
+    }
+}
+
+
+
+
diff --git a/android/renderscript/ProgramRaster.java b/android/renderscript/ProgramRaster.java
new file mode 100644
index 0000000..8b53828
--- /dev/null
+++ b/android/renderscript/ProgramRaster.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * Program raster is primarily used to specify whether point sprites are enabled and to control
+ * the culling mode. By default, back faces are culled.
+ **/
+@Deprecated
+public class ProgramRaster extends BaseObj {
+
+    /**
+     * @deprecated in API 16
+     **/
+    public enum CullMode {
+        /**
+         * @deprecated in API 16
+         **/
+        BACK (0),
+        /**
+         * @deprecated in API 16
+         **/
+        FRONT (1),
+        /**
+         * @deprecated in API 16
+         **/
+        NONE (2);
+
+        int mID;
+        CullMode(int id) {
+            mID = id;
+        }
+    }
+
+    boolean mPointSprite;
+    CullMode mCullMode;
+
+    ProgramRaster(long id, RenderScript rs) {
+        super(id, rs);
+
+        mPointSprite = false;
+        mCullMode = CullMode.BACK;
+    }
+
+    /**
+     * @deprecated in API 16
+     * Specifies whether vertices are rendered as screen aligned
+     * elements of a specified size
+     * @return whether point sprites are enabled
+     */
+    public boolean isPointSpriteEnabled() {
+        return mPointSprite;
+    }
+
+    /**
+     * @deprecated in API 16
+     * Specifies how triangles are culled based on their orientation
+     * @return cull mode
+     */
+    public CullMode getCullMode() {
+        return mCullMode;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static ProgramRaster CULL_BACK(RenderScript rs) {
+        if(rs.mProgramRaster_CULL_BACK == null) {
+            ProgramRaster.Builder builder = new ProgramRaster.Builder(rs);
+            builder.setCullMode(CullMode.BACK);
+            rs.mProgramRaster_CULL_BACK = builder.create();
+        }
+        return rs.mProgramRaster_CULL_BACK;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static ProgramRaster CULL_FRONT(RenderScript rs) {
+        if(rs.mProgramRaster_CULL_FRONT == null) {
+            ProgramRaster.Builder builder = new ProgramRaster.Builder(rs);
+            builder.setCullMode(CullMode.FRONT);
+            rs.mProgramRaster_CULL_FRONT = builder.create();
+        }
+        return rs.mProgramRaster_CULL_FRONT;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static ProgramRaster CULL_NONE(RenderScript rs) {
+        if(rs.mProgramRaster_CULL_NONE == null) {
+            ProgramRaster.Builder builder = new ProgramRaster.Builder(rs);
+            builder.setCullMode(CullMode.NONE);
+            rs.mProgramRaster_CULL_NONE = builder.create();
+        }
+        return rs.mProgramRaster_CULL_NONE;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static class Builder {
+        RenderScript mRS;
+        boolean mPointSprite;
+        CullMode mCullMode;
+
+        /**
+         * @deprecated in API 16
+         */
+        @UnsupportedAppUsage
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mPointSprite = false;
+            mCullMode = CullMode.BACK;
+        }
+
+        /**
+         * @deprecated in API 16
+         */
+        @UnsupportedAppUsage
+        public Builder setPointSpriteEnabled(boolean enable) {
+            mPointSprite = enable;
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+         */
+        public Builder setCullMode(CullMode m) {
+            mCullMode = m;
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+         */
+        @UnsupportedAppUsage
+        public ProgramRaster create() {
+            mRS.validate();
+            long id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID);
+            ProgramRaster programRaster = new ProgramRaster(id, mRS);
+            programRaster.mPointSprite = mPointSprite;
+            programRaster.mCullMode = mCullMode;
+            return programRaster;
+        }
+    }
+
+}
+
+
+
+
+
+
diff --git a/android/renderscript/ProgramStore.java b/android/renderscript/ProgramStore.java
new file mode 100644
index 0000000..c94d253
--- /dev/null
+++ b/android/renderscript/ProgramStore.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
+
+
+/**
+ * @hide
+ * <p>ProgramStore contains a set of parameters that control how
+ * the graphics hardware handles writes to the framebuffer.
+ * It could be used to:</p>
+ * <ul>
+ *   <li>enable/disable depth testing</li>
+ *   <li>specify wheather depth writes are performed</li>
+ *   <li>setup various blending modes for use in effects like
+ *     transparency</li>
+ *   <li>define write masks for color components written into the
+ *     framebuffer</li>
+ *  </ul>
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class ProgramStore extends BaseObj {
+    /**
+    * Specifies the function used to determine whether a fragment
+    * will be drawn during the depth testing stage in the rendering
+    * pipeline by comparing its value with that already in the depth
+    * buffer. DepthFunc is only valid when depth buffer is present
+    * and depth testing is enabled
+    */
+    public enum DepthFunc {
+
+        /**
+        * Always drawn
+        */
+        @UnsupportedAppUsage
+        ALWAYS (0),
+        /**
+        * Drawn if the incoming depth value is less than that in the
+        * depth buffer
+        */
+        @UnsupportedAppUsage
+        LESS (1),
+        /**
+        * Drawn if the incoming depth value is less or equal to that in
+        * the depth buffer
+        */
+        LESS_OR_EQUAL (2),
+        /**
+        * Drawn if the incoming depth value is greater than that in the
+        * depth buffer
+        */
+        GREATER (3),
+        /**
+        * Drawn if the incoming depth value is greater or equal to that
+        * in the depth buffer
+        */
+        GREATER_OR_EQUAL (4),
+        /**
+        * Drawn if the incoming depth value is equal to that in the
+        * depth buffer
+        */
+        EQUAL (5),
+        /**
+        * Drawn if the incoming depth value is not equal to that in the
+        * depth buffer
+        */
+        NOT_EQUAL (6);
+
+        int mID;
+        DepthFunc(int id) {
+            mID = id;
+        }
+    }
+
+    /**
+    * Specifies the functions used to combine incoming pixels with
+    * those already in the frame buffer.
+    *
+    * BlendSrcFunc describes how the coefficient used to scale the
+    * source pixels during the blending operation is computed
+    *
+    */
+    public enum BlendSrcFunc {
+        ZERO (0),
+        @UnsupportedAppUsage
+        ONE (1),
+        DST_COLOR (2),
+        ONE_MINUS_DST_COLOR (3),
+        @UnsupportedAppUsage
+        SRC_ALPHA (4),
+        ONE_MINUS_SRC_ALPHA (5),
+        DST_ALPHA (6),
+        ONE_MINUS_DST_ALPHA (7),
+        SRC_ALPHA_SATURATE (8);
+
+        int mID;
+        BlendSrcFunc(int id) {
+            mID = id;
+        }
+    }
+
+    /**
+    * Specifies the functions used to combine incoming pixels with
+    * those already in the frame buffer.
+    *
+    * BlendDstFunc describes how the coefficient used to scale the
+    * pixels already in the framebuffer is computed during the
+    * blending operation
+    *
+    */
+    public enum BlendDstFunc {
+        @UnsupportedAppUsage
+        ZERO (0),
+        @UnsupportedAppUsage
+        ONE (1),
+        SRC_COLOR (2),
+        ONE_MINUS_SRC_COLOR (3),
+        SRC_ALPHA (4),
+        @UnsupportedAppUsage
+        ONE_MINUS_SRC_ALPHA (5),
+        DST_ALPHA (6),
+        ONE_MINUS_DST_ALPHA (7);
+
+        int mID;
+        BlendDstFunc(int id) {
+            mID = id;
+        }
+    }
+
+    DepthFunc mDepthFunc;
+    boolean mDepthMask;
+    boolean mColorMaskR;
+    boolean mColorMaskG;
+    boolean mColorMaskB;
+    boolean mColorMaskA;
+    BlendSrcFunc mBlendSrc;
+    BlendDstFunc mBlendDst;
+    boolean mDither;
+
+    ProgramStore(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+    * Returns the function used to test writing into the depth
+    * buffer
+    * @return depth function
+    */
+    public DepthFunc getDepthFunc() {
+        return mDepthFunc;
+    }
+
+    /**
+    * Queries whether writes are enabled into the depth buffer
+    * @return depth mask
+    */
+    public boolean isDepthMaskEnabled() {
+        return mDepthMask;
+    }
+
+    /**
+    * Queries whether red channel is written
+    * @return red color channel mask
+    */
+    public boolean isColorMaskRedEnabled() {
+        return mColorMaskR;
+    }
+
+    /**
+    * Queries whether green channel is written
+    * @return green color channel mask
+    */
+    public boolean isColorMaskGreenEnabled() {
+        return mColorMaskG;
+    }
+
+    /**
+    * Queries whether blue channel is written
+    * @return blue color channel mask
+    */
+    public boolean isColorMaskBlueEnabled() {
+        return mColorMaskB;
+    }
+
+    /**
+    * Queries whether alpha channel is written
+    * @return alpha channel mask
+    */
+    public boolean isColorMaskAlphaEnabled() {
+        return mColorMaskA;
+    }
+
+    /**
+    * Specifies how the source blending factor is computed
+    * @return source blend function
+    */
+    public BlendSrcFunc getBlendSrcFunc() {
+        return mBlendSrc;
+    }
+
+    /**
+    * Specifies how the destination blending factor is computed
+    * @return destination blend function
+    */
+    public BlendDstFunc getBlendDstFunc() {
+        return mBlendDst;
+    }
+
+    /**
+    * Specifies whether colors are dithered before writing into the
+    * framebuffer
+    * @return whether dither is enabled
+    */
+    public boolean isDitherEnabled() {
+        return mDither;
+    }
+
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels are drawn if their depth value is less than
+    *    the stored value in the depth buffer. If the pixel is
+    *    drawn, its value is also stored in the depth buffer
+    *  - incoming pixels override the value stored in the color
+    *    buffer if it passes the depth test
+    *
+    *  @param rs Context to which the program will belong.
+    **/
+    public static ProgramStore BLEND_NONE_DEPTH_TEST(RenderScript rs) {
+        if(rs.mProgramStore_BLEND_NONE_DEPTH_TEST == null) {
+            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
+            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(true);
+            rs.mProgramStore_BLEND_NONE_DEPTH_TEST = builder.create();
+        }
+        return rs.mProgramStore_BLEND_NONE_DEPTH_TEST;
+    }
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels always pass the depth test and their value
+    *    is not stored in the depth buffer
+    *  - incoming pixels override the value stored in the color
+    *    buffer
+    *
+    *  @param rs Context to which the program will belong.
+    **/
+    public static ProgramStore BLEND_NONE_DEPTH_NONE(RenderScript rs) {
+        if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH == null) {
+            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(false);
+            rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH = builder.create();
+        }
+        return rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
+    }
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels are drawn if their depth value is less than
+    *    the stored value in the depth buffer. If the pixel is
+    *    drawn, its value is also stored in the depth buffer
+    *  - if the incoming (Source) pixel passes depth test, its value
+    *    is combined with the stored color (Dest) using the
+    *    following formula
+    *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
+    *
+    *  @param rs Context to which the program will belong.
+    **/
+    public static ProgramStore BLEND_ALPHA_DEPTH_TEST(RenderScript rs) {
+        if(rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST == null) {
+            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
+            builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(true);
+            rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST = builder.create();
+        }
+        return rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST;
+    }
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels always pass the depth test and their value
+    *    is not stored in the depth buffer
+    *  - incoming pixel's value is combined with the stored color
+    *    (Dest) using the following formula
+    *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
+    *
+    *  @param rs Context to which the program will belong.
+    **/
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    public static ProgramStore BLEND_ALPHA_DEPTH_NONE(RenderScript rs) {
+        if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH == null) {
+            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+            builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(false);
+            rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH = builder.create();
+        }
+        return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
+    }
+
+    /**
+    * Builder class for ProgramStore object. If the builder is left
+    * empty, the equivalent of BLEND_NONE_DEPTH_NONE would be
+    * returned
+    */
+    public static class Builder {
+        RenderScript mRS;
+        DepthFunc mDepthFunc;
+        boolean mDepthMask;
+        boolean mColorMaskR;
+        boolean mColorMaskG;
+        boolean mColorMaskB;
+        boolean mColorMaskA;
+        BlendSrcFunc mBlendSrc;
+        BlendDstFunc mBlendDst;
+        boolean mDither;
+
+        @UnsupportedAppUsage
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mDepthFunc = DepthFunc.ALWAYS;
+            mDepthMask = false;
+            mColorMaskR = true;
+            mColorMaskG = true;
+            mColorMaskB = true;
+            mColorMaskA = true;
+            mBlendSrc = BlendSrcFunc.ONE;
+            mBlendDst = BlendDstFunc.ZERO;
+        }
+
+        /**
+        * Specifies the depth testing behavior
+        *
+        * @param func function used for depth testing
+        *
+        * @return this
+        */
+        @UnsupportedAppUsage
+        public Builder setDepthFunc(DepthFunc func) {
+            mDepthFunc = func;
+            return this;
+        }
+
+        /**
+        * Enables writes into the depth buffer
+        *
+        * @param enable specifies whether depth writes are
+        *         enabled or disabled
+        *
+        * @return this
+        */
+        @UnsupportedAppUsage
+        public Builder setDepthMaskEnabled(boolean enable) {
+            mDepthMask = enable;
+            return this;
+        }
+
+        /**
+        * Enables writes into the color buffer
+        *
+        * @param r specifies whether red channel is written
+        * @param g specifies whether green channel is written
+        * @param b specifies whether blue channel is written
+        * @param a specifies whether alpha channel is written
+        *
+        * @return this
+        */
+        public Builder setColorMaskEnabled(boolean r, boolean g, boolean b, boolean a) {
+            mColorMaskR = r;
+            mColorMaskG = g;
+            mColorMaskB = b;
+            mColorMaskA = a;
+            return this;
+        }
+
+        /**
+        * Specifies how incoming pixels are combined with the pixels
+        * stored in the framebuffer
+        *
+        * @param src specifies how the source blending factor is
+        *            computed
+        * @param dst specifies how the destination blending factor is
+        *            computed
+        *
+        * @return this
+        */
+        @UnsupportedAppUsage
+        public Builder setBlendFunc(BlendSrcFunc src, BlendDstFunc dst) {
+            mBlendSrc = src;
+            mBlendDst = dst;
+            return this;
+        }
+
+        /**
+        * Enables dithering
+        *
+        * @param enable specifies whether dithering is enabled or
+        *               disabled
+        *
+        * @return this
+        */
+        @UnsupportedAppUsage
+        public Builder setDitherEnabled(boolean enable) {
+            mDither = enable;
+            return this;
+        }
+
+        /**
+        * Creates a program store from the current state of the builder
+        */
+        @UnsupportedAppUsage
+        public ProgramStore create() {
+            mRS.validate();
+            long id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
+                                             mDepthMask, mDither,
+                                             mBlendSrc.mID, mBlendDst.mID, mDepthFunc.mID);
+            ProgramStore programStore = new ProgramStore(id, mRS);
+            programStore.mDepthFunc = mDepthFunc;
+            programStore.mDepthMask = mDepthMask;
+            programStore.mColorMaskR = mColorMaskR;
+            programStore.mColorMaskG = mColorMaskG;
+            programStore.mColorMaskB = mColorMaskB;
+            programStore.mColorMaskA = mColorMaskA;
+            programStore.mBlendSrc = mBlendSrc;
+            programStore.mBlendDst = mBlendDst;
+            programStore.mDither = mDither;
+            return programStore;
+        }
+    }
+
+}
+
+
+
+
diff --git a/android/renderscript/ProgramVertex.java b/android/renderscript/ProgramVertex.java
new file mode 100644
index 0000000..ecd8a31
--- /dev/null
+++ b/android/renderscript/ProgramVertex.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @hide
+ * <p>The RenderScript vertex program, also known as a vertex shader, describes a stage in
+ * the graphics pipeline responsible for manipulating geometric data in a user-defined way.
+ * The object is constructed by providing the RenderScript system with the following data:</p>
+ * <ul>
+ *   <li>Element describing its varying inputs or attributes</li>
+ *   <li>GLSL shader string that defines the body of the program</li>
+ *   <li>a Type that describes the layout of an Allocation containing constant or uniform inputs</li>
+ * </ul>
+ *
+ * <p>Once the program is created, you bind it to the graphics context, RenderScriptGL, and it will be used for
+ * all subsequent draw calls until you bind a new program. If the program has constant inputs,
+ * the user needs to bind an allocation containing those inputs. The allocation's type must match
+ * the one provided during creation. The RenderScript library then does all the necessary plumbing
+ * to send those constants to the graphics hardware. Varying inputs to the shader, such as position, normal,
+ * and texture coordinates are matched by name between the input Element and the Mesh object being drawn.
+ * The signatures don't have to be exact or in any strict order. As long as the input name in the shader
+ * matches a channel name and size available on the mesh, the runtime takes care of connecting the
+ * two. Unlike OpenGL, there is no need to link the vertex and fragment programs.</p>
+ **/
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * ProgramVertex, also know as a vertex shader, describes a
+ * stage in the graphics pipeline responsible for manipulating
+ * geometric data in a user-defined way.
+ *
+ **/
+@Deprecated
+public class ProgramVertex extends Program {
+
+    ProgramVertex(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * @deprecated in API 16
+     * @return number of input attribute elements
+     */
+    public int getInputCount() {
+        return mInputs != null ? mInputs.length : 0;
+    }
+
+    /**
+     * @deprecated in API 16
+     * @param slot location of the input to return
+     * @return input attribute element
+     */
+    public Element getInput(int slot) {
+        if (slot < 0 || slot >= mInputs.length) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        return mInputs[slot];
+    }
+
+    /**
+     * @hide
+     * @deprecated in API 16
+     * Builder class for creating ProgramVertex objects.
+     * The builder starts empty and the user must minimally provide
+     * the GLSL shader code, and the varying inputs. Constant, or
+     * uniform parameters to the shader may optionally be provided as
+     * well.
+     *
+     **/
+    public static class Builder extends BaseProgramBuilder {
+        /**
+         * @deprecated in API 16
+         * Create a builder object.
+         *
+         * @param rs Context to which the program will belong.
+         */
+        @UnsupportedAppUsage
+        public Builder(RenderScript rs) {
+            super(rs);
+        }
+
+        /**
+         * @deprecated in API 16
+         * Add varying inputs to the program
+         *
+         * @param e element describing the layout of the varying input
+         *          structure
+         * @return  self
+         */
+        @UnsupportedAppUsage
+        public Builder addInput(Element e) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mInputCount >= MAX_INPUT) {
+                throw new RSIllegalArgumentException("Max input count exceeded.");
+            }
+            if (e.isComplex()) {
+                throw new RSIllegalArgumentException("Complex elements not allowed.");
+            }
+            mInputs[mInputCount++] = e;
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Creates ProgramVertex from the current state of the builder
+         *
+         * @return  ProgramVertex
+         */
+        @UnsupportedAppUsage
+        public ProgramVertex create() {
+            mRS.validate();
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = ProgramParam.INPUT.mID;
+                tmp[idx++] = mInputs[i].getID(mRS);
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = ProgramParam.OUTPUT.mID;
+                tmp[idx++] = mOutputs[i].getID(mRS);
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = ProgramParam.CONSTANT.mID;
+                tmp[idx++] = mConstants[i].getID(mRS);
+            }
+            for (int i=0; i < mTextureCount; i++) {
+                tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
+                tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
+            }
+
+            long id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
+            ProgramVertex pv = new ProgramVertex(id, mRS);
+            initProgram(pv);
+            return pv;
+        }
+    }
+
+}
diff --git a/android/renderscript/ProgramVertexFixedFunction.java b/android/renderscript/ProgramVertexFixedFunction.java
new file mode 100644
index 0000000..4cf2f4c
--- /dev/null
+++ b/android/renderscript/ProgramVertexFixedFunction.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * ProgramVertexFixedFunction is a helper class that provides a
+ * simple way to create a fixed function emulation vertex shader
+ * without writing any GLSL code.
+ *
+ **/
+@Deprecated
+public class ProgramVertexFixedFunction extends ProgramVertex {
+
+    ProgramVertexFixedFunction(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * @deprecated in API 16
+     * Binds the constant buffer containing fixed function emulation
+     * matrices
+     *
+     * @param va allocation containing fixed function matrices
+     */
+    @UnsupportedAppUsage
+    public void bindConstants(Constants va) {
+        mRS.validate();
+        bindConstants(va.getAllocation(), 0);
+    }
+
+    static class InternalBuilder extends BaseProgramBuilder {
+        /**
+         * @deprecated in API 16
+         */
+        public InternalBuilder(RenderScript rs) {
+            super(rs);
+        }
+
+        /**
+         * @deprecated in API 16
+         */
+        public InternalBuilder addInput(Element e) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mInputCount >= MAX_INPUT) {
+                throw new RSIllegalArgumentException("Max input count exceeded.");
+            }
+            if (e.isComplex()) {
+                throw new RSIllegalArgumentException("Complex elements not allowed.");
+            }
+            mInputs[mInputCount++] = e;
+            return this;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Creates ProgramVertexFixedFunction from the current state of
+         * the builder
+         *
+         * @return  ProgramVertexFixedFunction
+         */
+        public ProgramVertexFixedFunction create() {
+            mRS.validate();
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = ProgramParam.INPUT.mID;
+                tmp[idx++] = mInputs[i].getID(mRS);
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = ProgramParam.OUTPUT.mID;
+                tmp[idx++] = mOutputs[i].getID(mRS);
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = ProgramParam.CONSTANT.mID;
+                tmp[idx++] = mConstants[i].getID(mRS);
+            }
+            for (int i=0; i < mTextureCount; i++) {
+                tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
+                tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
+            }
+
+            long id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
+            ProgramVertexFixedFunction pv = new ProgramVertexFixedFunction(id, mRS);
+            initProgram(pv);
+            return pv;
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    public static class Builder {
+        boolean mTextureMatrixEnable;
+        String mShader;
+        RenderScript mRS;
+
+        /**
+         * @deprecated in API 16
+         * Creates a builder for fixed function vertex program
+         *
+         * @param rs Context to which the program will belong.
+         */
+        @UnsupportedAppUsage
+        public Builder(RenderScript rs) {
+            mRS = rs;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Specifies whether texture matrix calculations are to be added
+         * to the shader
+         *
+         */
+        public Builder setTextureMatrixEnable(boolean enable) {
+            mTextureMatrixEnable = enable;
+            return this;
+        }
+        static Type getConstantInputType(RenderScript rs) {
+            Element.Builder b = new Element.Builder(rs);
+            b.add(Element.MATRIX4X4(rs), "MV");
+            b.add(Element.MATRIX4X4(rs), "P");
+            b.add(Element.MATRIX4X4(rs), "TexMatrix");
+            b.add(Element.MATRIX4X4(rs), "MVP");
+
+            Type.Builder typeBuilder = new Type.Builder(rs, b.create());
+            typeBuilder.setX(1);
+            return typeBuilder.create();
+        }
+
+        private void buildShaderString() {
+
+            mShader  = "//rs_shader_internal\n";
+            mShader += "varying vec4 varColor;\n";
+            mShader += "varying vec2 varTex0;\n";
+
+            mShader += "void main() {\n";
+            mShader += "  gl_Position = UNI_MVP * ATTRIB_position;\n";
+            mShader += "  gl_PointSize = 1.0;\n";
+
+            mShader += "  varColor = ATTRIB_color;\n";
+            if (mTextureMatrixEnable) {
+                mShader += "  varTex0 = (UNI_TexMatrix * vec4(ATTRIB_texture0, 0.0, 1.0)).xy;\n";
+            } else {
+                mShader += "  varTex0 = ATTRIB_texture0;\n";
+            }
+            mShader += "}\n";
+        }
+
+        /**
+         * @deprecated in API 16
+         * Creates ProgramVertexFixedFunction from the current state of
+         * the builder
+         *
+         * @return Fixed function emulation ProgramVertex
+         */
+        @UnsupportedAppUsage
+        public ProgramVertexFixedFunction create() {
+            buildShaderString();
+
+            InternalBuilder sb = new InternalBuilder(mRS);
+            sb.setShader(mShader);
+            sb.addConstant(getConstantInputType(mRS));
+
+            Element.Builder b = new Element.Builder(mRS);
+            b.add(Element.F32_4(mRS), "position");
+            b.add(Element.F32_4(mRS), "color");
+            b.add(Element.F32_3(mRS), "normal");
+            b.add(Element.F32_2(mRS), "texture0");
+            sb.addInput(b.create());
+
+            return sb.create();
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     * Helper class to store modelview, projection and texture
+     * matrices for ProgramVertexFixedFunction
+     *
+     */
+    public static class Constants {
+        static final int MODELVIEW_OFFSET = 0;
+        static final int PROJECTION_OFFSET = 16;
+        static final int TEXTURE_OFFSET = 32;
+
+        Matrix4f mModel;
+        Matrix4f mProjection;
+        Matrix4f mTexture;
+
+        Allocation mAlloc;
+        Allocation getAllocation() {
+            return mAlloc;
+        }
+        private FieldPacker mIOBuffer;
+
+        /**
+        * @deprecated in API 16
+        * Creates a buffer to store fixed function emulation matrices
+        *
+        * @param rs Context to which the allocation will belong.
+        **/
+        @UnsupportedAppUsage
+        public Constants(RenderScript rs) {
+            Type constInputType = ProgramVertexFixedFunction.Builder.getConstantInputType(rs);
+            mAlloc = Allocation.createTyped(rs, constInputType);
+            int bufferSize = constInputType.getElement().getBytesSize()*
+                             constInputType.getCount();
+            mIOBuffer = new FieldPacker(bufferSize);
+            mModel = new Matrix4f();
+            mProjection = new Matrix4f();
+            mTexture = new Matrix4f();
+            setModelview(new Matrix4f());
+            setProjection(new Matrix4f());
+            setTexture(new Matrix4f());
+        }
+
+        /**
+        * @deprecated in API 16
+        * Forces deallocation of memory backing the contant matrices.
+        * Normally, this is unnecessary and will be garbage collected
+        *
+        */
+        public void destroy() {
+            mAlloc.destroy();
+            mAlloc = null;
+        }
+
+        private void addToBuffer(int offset, Matrix4f m) {
+            mIOBuffer.reset(offset);
+            for(int i = 0; i < 16; i ++) {
+                mIOBuffer.addF32(m.mMat[i]);
+            }
+            // Reset the buffer back to the end, since we want to flush all of
+            // the contents back (and not just what we wrote now).
+            mIOBuffer.reset(mIOBuffer.getData().length);
+            mAlloc.setFromFieldPacker(0, mIOBuffer);
+        }
+
+        /**
+        * @deprecated in API 16
+        * Sets the modelview matrix in the fixed function matrix buffer
+        *
+        * @param m modelview matrix
+        */
+        public void setModelview(Matrix4f m) {
+            mModel.load(m);
+            addToBuffer(MODELVIEW_OFFSET*4, m);
+        }
+
+        /**
+        * @deprecated in API 16
+        * Sets the projection matrix in the fixed function matrix buffer
+        *
+        * @param m projection matrix
+        */
+        @UnsupportedAppUsage
+        public void setProjection(Matrix4f m) {
+            mProjection.load(m);
+            addToBuffer(PROJECTION_OFFSET*4, m);
+        }
+
+        /**
+        * @deprecated in API 16
+        * Sets the texture matrix in the fixed function matrix buffer.
+        * Texture matrix must be enabled in the
+        * ProgramVertexFixedFunction builder for the shader to utilize
+        * it.
+        *
+        * @param m modelview matrix
+        */
+        public void setTexture(Matrix4f m) {
+            mTexture.load(m);
+            addToBuffer(TEXTURE_OFFSET*4, m);
+        }
+    }
+}
diff --git a/android/renderscript/RSDriverException.java b/android/renderscript/RSDriverException.java
new file mode 100644
index 0000000..3d0f0bf
--- /dev/null
+++ b/android/renderscript/RSDriverException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Base class for all exceptions thrown by the Android
+ * RenderScript
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class RSDriverException extends RSRuntimeException {
+    public RSDriverException(String string) {
+        super(string);
+    }
+}
+
+
+
diff --git a/android/renderscript/RSIllegalArgumentException.java b/android/renderscript/RSIllegalArgumentException.java
new file mode 100644
index 0000000..d0ac5b6
--- /dev/null
+++ b/android/renderscript/RSIllegalArgumentException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Base class for all exceptions thrown by the Android
+ * RenderScript
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class RSIllegalArgumentException extends RSRuntimeException {
+    public RSIllegalArgumentException(String string) {
+        super(string);
+    }
+}
+
+
diff --git a/android/renderscript/RSInvalidStateException.java b/android/renderscript/RSInvalidStateException.java
new file mode 100644
index 0000000..5eea419
--- /dev/null
+++ b/android/renderscript/RSInvalidStateException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Base class for all exceptions thrown by the Android
+ * RenderScript
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class RSInvalidStateException extends RSRuntimeException {
+    public RSInvalidStateException(String string) {
+        super(string);
+    }
+}
+
+
+
diff --git a/android/renderscript/RSRuntimeException.java b/android/renderscript/RSRuntimeException.java
new file mode 100644
index 0000000..d52a1c1
--- /dev/null
+++ b/android/renderscript/RSRuntimeException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Base class for all exceptions thrown by the Android
+ * RenderScript
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class RSRuntimeException
+  extends java.lang.RuntimeException {
+    public RSRuntimeException(String string) {
+        super(string);
+    }
+}
+
diff --git a/android/renderscript/RSSurfaceView.java b/android/renderscript/RSSurfaceView.java
new file mode 100644
index 0000000..05c0112
--- /dev/null
+++ b/android/renderscript/RSSurfaceView.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * The Surface View for a graphics renderscript (RenderScriptGL) to draw on.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ */
+@Deprecated
+public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+    private SurfaceHolder mSurfaceHolder;
+    private RenderScriptGL mRS;
+
+    /**
+     * @deprecated in API 16
+     * Standard View constructor. In order to render something, you
+     * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+     * register a renderer.
+     */
+    @UnsupportedAppUsage
+    public RSSurfaceView(Context context) {
+        super(context);
+        init();
+        //Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
+    }
+
+    /**
+     * @deprecated in API 16
+     * Standard View constructor. In order to render something, you
+     * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+     * register a renderer.
+     */
+    @UnsupportedAppUsage
+    public RSSurfaceView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+        //Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
+    }
+
+    private void init() {
+        // Install a SurfaceHolder.Callback so we get notified when the
+        // underlying surface is created and destroyed
+        SurfaceHolder holder = getHolder();
+        holder.addCallback(this);
+    }
+
+    /**
+     * @deprecated in API 16
+     * This method is part of the SurfaceHolder.Callback interface, and is
+     * not normally called or subclassed by clients of RSSurfaceView.
+     */
+    public void surfaceCreated(SurfaceHolder holder) {
+        mSurfaceHolder = holder;
+    }
+
+    /**
+     * @deprecated in API 16
+     * This method is part of the SurfaceHolder.Callback interface, and is
+     * not normally called or subclassed by clients of RSSurfaceView.
+     */
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        synchronized (this) {
+            // Surface will be destroyed when we return
+            if (mRS != null) {
+                mRS.setSurface(null, 0, 0);
+            }
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     * This method is part of the SurfaceHolder.Callback interface, and is
+     * not normally called or subclassed by clients of RSSurfaceView.
+     */
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        synchronized (this) {
+            if (mRS != null) {
+                mRS.setSurface(holder, w, h);
+            }
+        }
+    }
+
+   /**
+     * @deprecated in API 16
+     * Inform the view that the activity is paused. The owner of this view must
+     * call this method when the activity is paused. Calling this method will
+     * pause the rendering thread.
+     * Must not be called before a renderer has been set.
+     */
+    public void pause() {
+        if(mRS != null) {
+            mRS.pause();
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     * Inform the view that the activity is resumed. The owner of this view must
+     * call this method when the activity is resumed. Calling this method will
+     * recreate the OpenGL display and resume the rendering
+     * thread.
+     * Must not be called before a renderer has been set.
+     */
+    public void resume() {
+        if(mRS != null) {
+            mRS.resume();
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     **/
+    public RenderScriptGL createRenderScriptGL(RenderScriptGL.SurfaceConfig sc) {
+      RenderScriptGL rs = new RenderScriptGL(this.getContext(), sc);
+        setRenderScriptGL(rs);
+        return rs;
+    }
+
+    /**
+     * @deprecated in API 16
+     **/
+    public void destroyRenderScriptGL() {
+        synchronized (this) {
+            mRS.destroy();
+            mRS = null;
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     **/
+    public void setRenderScriptGL(RenderScriptGL rs) {
+        mRS = rs;
+    }
+
+    /**
+     * @deprecated in API 16
+     **/
+    public RenderScriptGL getRenderScriptGL() {
+        return mRS;
+    }
+}
diff --git a/android/renderscript/RSTextureView.java b/android/renderscript/RSTextureView.java
new file mode 100644
index 0000000..ed68fc3
--- /dev/null
+++ b/android/renderscript/RSTextureView.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.util.AttributeSet;
+import android.view.TextureView;
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * The Texture View for a graphics renderscript (RenderScriptGL)
+ * to draw on.
+ *
+ */
+@Deprecated
+public class RSTextureView extends TextureView implements TextureView.SurfaceTextureListener {
+    private RenderScriptGL mRS;
+    private SurfaceTexture mSurfaceTexture;
+
+    /**
+     * @deprecated in API 16
+     * Standard View constructor. In order to render something, you
+     * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+     * register a renderer.
+     */
+    public RSTextureView(Context context) {
+        super(context);
+        init();
+        //Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
+    }
+
+    /**
+     * @deprecated in API 16
+     * Standard View constructor. In order to render something, you
+     * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+     * register a renderer.
+     */
+    public RSTextureView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+        //Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
+    }
+
+    private void init() {
+        setSurfaceTextureListener(this);
+        //android.util.Log.e("rs", "getSurfaceTextureListerner " + getSurfaceTextureListener());
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    @Override
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureAvailable");
+        mSurfaceTexture = surface;
+
+        if (mRS != null) {
+            mRS.setSurfaceTexture(mSurfaceTexture, width, height);
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    @Override
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureSizeChanged");
+        mSurfaceTexture = surface;
+
+        if (mRS != null) {
+            mRS.setSurfaceTexture(mSurfaceTexture, width, height);
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    @Override
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureDestroyed");
+        mSurfaceTexture = surface;
+
+        if (mRS != null) {
+            mRS.setSurfaceTexture(null, 0, 0);
+        }
+
+        return true;
+    }
+
+    /**
+     * @deprecated in API 16
+     */
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureUpdated");
+        mSurfaceTexture = surface;
+    }
+
+   /**
+     * @deprecated in API 16
+     * Inform the view that the activity is paused. The owner of this view must
+     * call this method when the activity is paused. Calling this method will
+     * pause the rendering thread.
+     * Must not be called before a renderer has been set.
+     */
+    public void pause() {
+        if(mRS != null) {
+            mRS.pause();
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     * Inform the view that the activity is resumed. The owner of this view must
+     * call this method when the activity is resumed. Calling this method will
+     * recreate the OpenGL display and resume the rendering
+     * thread.
+     * Must not be called before a renderer has been set.
+     */
+    public void resume() {
+        if(mRS != null) {
+            mRS.resume();
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     * Create a new RenderScriptGL object and attach it to the
+     * TextureView if present.
+     *
+     *
+     * @param sc The RS surface config to create.
+     *
+     * @return RenderScriptGL The new object created.
+     */
+    public RenderScriptGL createRenderScriptGL(RenderScriptGL.SurfaceConfig sc) {
+        RenderScriptGL rs = new RenderScriptGL(this.getContext(), sc);
+        setRenderScriptGL(rs);
+        if (mSurfaceTexture != null) {
+            mRS.setSurfaceTexture(mSurfaceTexture, getWidth(), getHeight());
+        }
+        return rs;
+    }
+
+    /**
+     * @deprecated in API 16
+     * Destroy the RenderScriptGL object associated with this
+     * TextureView.
+     */
+    public void destroyRenderScriptGL() {
+        mRS.destroy();
+        mRS = null;
+    }
+
+    /**
+     * @deprecated in API 16
+     * Set a new RenderScriptGL object.  This also will attach the
+     * new object to the TextureView if present.
+     *
+     * @param rs The new RS object.
+     */
+    public void setRenderScriptGL(RenderScriptGL rs) {
+        mRS = rs;
+        if (mSurfaceTexture != null) {
+            mRS.setSurfaceTexture(mSurfaceTexture, getWidth(), getHeight());
+        }
+    }
+
+    /**
+     * @deprecated in API 16
+     * Returns the previously set RenderScriptGL object.
+     *
+     * @return RenderScriptGL
+     */
+    public RenderScriptGL getRenderScriptGL() {
+        return mRS;
+    }
+}
+
diff --git a/android/renderscript/RenderScript.java b/android/renderscript/RenderScript.java
new file mode 100644
index 0000000..855cfdc
--- /dev/null
+++ b/android/renderscript/RenderScript.java
@@ -0,0 +1,1674 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.graphics.SurfaceTexture;
+import android.os.SystemProperties;
+import android.os.Trace;
+import android.util.Log;
+import android.view.Surface;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+// TODO: Clean up the whitespace that separates methods in this class.
+
+/**
+ * This class provides access to a RenderScript context, which controls RenderScript
+ * initialization, resource management, and teardown. An instance of the RenderScript
+ * class must be created before any other RS objects can be created.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class RenderScript {
+    static final long TRACE_TAG = Trace.TRACE_TAG_RS;
+
+    static final String LOG_TAG = "RenderScript_jni";
+    static final boolean DEBUG  = false;
+    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
+    static final boolean LOG_ENABLED = false;
+
+    static private ArrayList<RenderScript> mProcessContextList = new ArrayList<RenderScript>();
+    private boolean mIsProcessContext = false;
+    private int mContextFlags = 0;
+    private int mContextSdkVersion = 0;
+
+
+    private Context mApplicationContext;
+
+    /*
+     * We use a class initializer to allow the native code to cache some
+     * field offsets.
+     */
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // TODO: now used locally; remove?
+    static boolean sInitialized;
+    native static void _nInit();
+
+    static Object sRuntime;
+    static Method registerNativeAllocation;
+    static Method registerNativeFree;
+
+    /*
+     * Context creation flag that specifies a normal context.
+    */
+    public static final int CREATE_FLAG_NONE = 0x0000;
+
+    /*
+     * Context creation flag which specifies a context optimized for low
+     * latency over peak performance. This is a hint and may have no effect
+     * on some implementations.
+    */
+    public static final int CREATE_FLAG_LOW_LATENCY = 0x0002;
+
+    /*
+     * Context creation flag which specifies a context optimized for long
+     * battery life over peak performance. This is a hint and may have no effect
+     * on some implementations.
+    */
+    public static final int CREATE_FLAG_LOW_POWER = 0x0004;
+
+    /**
+     * @hide
+     * Context creation flag which instructs the implementation to wait for
+     * a debugger to be attached before continuing execution.
+    */
+    public static final int CREATE_FLAG_WAIT_FOR_ATTACH = 0x0008;
+
+
+    /*
+     * Detect the bitness of the VM to allow FieldPacker to do the right thing.
+     */
+    static native int rsnSystemGetPointerSize();
+    @UnsupportedAppUsage
+    static int sPointerSize;
+
+    static {
+        sInitialized = false;
+        if (!SystemProperties.getBoolean("config.disable_renderscript", false)) {
+            try {
+                Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
+                Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
+                sRuntime = get_runtime.invoke(null);
+                registerNativeAllocation =
+                        vm_runtime.getDeclaredMethod("registerNativeAllocation", Long.TYPE);
+                registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Long.TYPE);
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Error loading GC methods: " + e);
+                throw new RSRuntimeException("Error loading GC methods: " + e);
+            }
+            try {
+                System.loadLibrary("rs_jni");
+                _nInit();
+                sInitialized = true;
+                sPointerSize = rsnSystemGetPointerSize();
+            } catch (UnsatisfiedLinkError e) {
+                Log.e(LOG_TAG, "Error loading RS jni library: " + e);
+                throw new RSRuntimeException("Error loading RS jni library: " + e);
+            }
+        }
+    }
+
+    // Non-threadsafe functions.
+    native long  nDeviceCreate();
+    native void nDeviceDestroy(long dev);
+    native void nDeviceSetConfig(long dev, int param, int value);
+    native int nContextGetUserMessage(long con, int[] data);
+    native String nContextGetErrorMessage(long con);
+    native int  nContextPeekMessage(long con, int[] subID);
+    native void nContextInitToClient(long con);
+    native void nContextDeinitToClient(long con);
+
+    // this should be a monotonically increasing ID
+    // used in conjunction with the API version of a device
+    static final long sMinorVersion = 1;
+
+    /**
+     * @hide
+     *
+     * Only exist to be compatible with old version RenderScript Support lib.
+     * Will eventually be removed.
+     *
+     * @return Always return 1
+     *
+     */
+    @UnsupportedAppUsage
+    public static long getMinorID() {
+        return 1;
+    }
+
+
+    /**
+     * Returns an identifier that can be used to identify a particular
+     * minor version of RS.
+     *
+     * @return The minor RenderScript version number
+     *
+     */
+    public static long getMinorVersion() {
+        return sMinorVersion;
+    }
+
+    /**
+     * ContextType specifies the specific type of context to be created.
+     *
+     */
+    public enum ContextType {
+        /**
+         * NORMAL context, this is the default and what shipping apps should
+         * use.
+         */
+        NORMAL (0),
+
+        /**
+         * DEBUG context, perform extra runtime checks to validate the
+         * kernels and APIs are being used as intended.  Get and SetElementAt
+         * will be bounds checked in this mode.
+         */
+        DEBUG (1),
+
+        /**
+         * PROFILE context, Intended to be used once the first time an
+         * application is run on a new device.  This mode allows the runtime to
+         * do additional testing and performance tuning.
+         */
+        PROFILE (2);
+
+        int mID;
+        ContextType(int id) {
+            mID = id;
+        }
+    }
+
+    ContextType mContextType;
+    ReentrantReadWriteLock mRWLock;
+
+    // Methods below are wrapped to protect the non-threadsafe
+    // lockless fifo.
+    native long  rsnContextCreateGL(long dev, int ver, int sdkVer,
+                 int colorMin, int colorPref,
+                 int alphaMin, int alphaPref,
+                 int depthMin, int depthPref,
+                 int stencilMin, int stencilPref,
+                 int samplesMin, int samplesPref, float samplesQ, int dpi);
+    synchronized long nContextCreateGL(long dev, int ver, int sdkVer,
+                 int colorMin, int colorPref,
+                 int alphaMin, int alphaPref,
+                 int depthMin, int depthPref,
+                 int stencilMin, int stencilPref,
+                 int samplesMin, int samplesPref, float samplesQ, int dpi) {
+        return rsnContextCreateGL(dev, ver, sdkVer, colorMin, colorPref,
+                                  alphaMin, alphaPref, depthMin, depthPref,
+                                  stencilMin, stencilPref,
+                                  samplesMin, samplesPref, samplesQ, dpi);
+    }
+    native long  rsnContextCreate(long dev, int ver, int sdkVer, int contextType);
+    synchronized long nContextCreate(long dev, int ver, int sdkVer, int contextType) {
+        return rsnContextCreate(dev, ver, sdkVer, contextType);
+    }
+    native void rsnContextDestroy(long con);
+    synchronized void nContextDestroy() {
+        validate();
+
+        // take teardown lock
+        // teardown lock can only be taken when no objects are being destroyed
+        ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
+        wlock.lock();
+
+        long curCon = mContext;
+        // context is considered dead as of this point
+        mContext = 0;
+
+        wlock.unlock();
+        rsnContextDestroy(curCon);
+    }
+    native void rsnContextSetSurface(long con, int w, int h, Surface sur);
+    synchronized void nContextSetSurface(int w, int h, Surface sur) {
+        validate();
+        rsnContextSetSurface(mContext, w, h, sur);
+    }
+    native void rsnContextSetSurfaceTexture(long con, int w, int h, SurfaceTexture sur);
+    synchronized void nContextSetSurfaceTexture(int w, int h, SurfaceTexture sur) {
+        validate();
+        rsnContextSetSurfaceTexture(mContext, w, h, sur);
+    }
+    native void rsnContextSetPriority(long con, int p);
+    synchronized void nContextSetPriority(int p) {
+        validate();
+        rsnContextSetPriority(mContext, p);
+    }
+    native void rsnContextSetCacheDir(long con, String cacheDir);
+    synchronized void nContextSetCacheDir(String cacheDir) {
+        validate();
+        rsnContextSetCacheDir(mContext, cacheDir);
+    }
+    native void rsnContextDump(long con, int bits);
+    synchronized void nContextDump(int bits) {
+        validate();
+        rsnContextDump(mContext, bits);
+    }
+    native void rsnContextFinish(long con);
+    synchronized void nContextFinish() {
+        validate();
+        rsnContextFinish(mContext);
+    }
+
+    native void rsnContextSendMessage(long con, int id, int[] data);
+    synchronized void nContextSendMessage(int id, int[] data) {
+        validate();
+        rsnContextSendMessage(mContext, id, data);
+    }
+
+    native void rsnContextBindRootScript(long con, long script);
+    synchronized void nContextBindRootScript(long script) {
+        validate();
+        rsnContextBindRootScript(mContext, script);
+    }
+    native void rsnContextBindSampler(long con, int sampler, int slot);
+    synchronized void nContextBindSampler(int sampler, int slot) {
+        validate();
+        rsnContextBindSampler(mContext, sampler, slot);
+    }
+    native void rsnContextBindProgramStore(long con, long pfs);
+    synchronized void nContextBindProgramStore(long pfs) {
+        validate();
+        rsnContextBindProgramStore(mContext, pfs);
+    }
+    native void rsnContextBindProgramFragment(long con, long pf);
+    synchronized void nContextBindProgramFragment(long pf) {
+        validate();
+        rsnContextBindProgramFragment(mContext, pf);
+    }
+    native void rsnContextBindProgramVertex(long con, long pv);
+    synchronized void nContextBindProgramVertex(long pv) {
+        validate();
+        rsnContextBindProgramVertex(mContext, pv);
+    }
+    native void rsnContextBindProgramRaster(long con, long pr);
+    synchronized void nContextBindProgramRaster(long pr) {
+        validate();
+        rsnContextBindProgramRaster(mContext, pr);
+    }
+    native void rsnContextPause(long con);
+    synchronized void nContextPause() {
+        validate();
+        rsnContextPause(mContext);
+    }
+    native void rsnContextResume(long con);
+    synchronized void nContextResume() {
+        validate();
+        rsnContextResume(mContext);
+    }
+
+    native long rsnClosureCreate(long con, long kernelID, long returnValue,
+        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
+        long[] depFieldIDs);
+    synchronized long nClosureCreate(long kernelID, long returnValue,
+        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
+        long[] depFieldIDs) {
+      validate();
+      long c = rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
+          sizes, depClosures, depFieldIDs);
+      if (c == 0) {
+          throw new RSRuntimeException("Failed creating closure.");
+      }
+      return c;
+    }
+
+    native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
+        long[] fieldIDs, long[] values, int[] sizes);
+    synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
+        long[] fieldIDs, long[] values, int[] sizes) {
+      validate();
+      long c = rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
+          values, sizes);
+      if (c == 0) {
+          throw new RSRuntimeException("Failed creating closure.");
+      }
+      return c;
+    }
+
+    native void rsnClosureSetArg(long con, long closureID, int index,
+      long value, int size);
+    synchronized void nClosureSetArg(long closureID, int index, long value,
+        int size) {
+      validate();
+      rsnClosureSetArg(mContext, closureID, index, value, size);
+    }
+
+    native void rsnClosureSetGlobal(long con, long closureID, long fieldID,
+        long value, int size);
+    // Does this have to be synchronized?
+    synchronized void nClosureSetGlobal(long closureID, long fieldID,
+        long value, int size) {
+      validate(); // TODO: is this necessary?
+      rsnClosureSetGlobal(mContext, closureID, fieldID, value, size);
+    }
+
+    native long rsnScriptGroup2Create(long con, String name, String cachePath,
+                                      long[] closures);
+    synchronized long nScriptGroup2Create(String name, String cachePath,
+                                          long[] closures) {
+      validate();
+      long g = rsnScriptGroup2Create(mContext, name, cachePath, closures);
+      if (g == 0) {
+          throw new RSRuntimeException("Failed creating script group.");
+      }
+      return g;
+    }
+
+    native void rsnScriptGroup2Execute(long con, long groupID);
+    synchronized void nScriptGroup2Execute(long groupID) {
+      validate();
+      rsnScriptGroup2Execute(mContext, groupID);
+    }
+
+    native void rsnAssignName(long con, long obj, byte[] name);
+    synchronized void nAssignName(long obj, byte[] name) {
+        validate();
+        rsnAssignName(mContext, obj, name);
+    }
+    native String rsnGetName(long con, long obj);
+    synchronized String nGetName(long obj) {
+        validate();
+        return rsnGetName(mContext, obj);
+    }
+
+    // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
+    native void rsnObjDestroy(long con, long id);
+    void nObjDestroy(long id) {
+        // There is a race condition here.  The calling code may be run
+        // by the gc while teardown is occuring.  This protects againts
+        // deleting dead objects.
+        if (mContext != 0) {
+            rsnObjDestroy(mContext, id);
+        }
+    }
+
+    native long rsnElementCreate(long con, long type, int kind, boolean norm, int vecSize);
+    synchronized long nElementCreate(long type, int kind, boolean norm, int vecSize) {
+        validate();
+        return rsnElementCreate(mContext, type, kind, norm, vecSize);
+    }
+    native long rsnElementCreate2(long con, long[] elements, String[] names, int[] arraySizes);
+    synchronized long nElementCreate2(long[] elements, String[] names, int[] arraySizes) {
+        validate();
+        return rsnElementCreate2(mContext, elements, names, arraySizes);
+    }
+    native void rsnElementGetNativeData(long con, long id, int[] elementData);
+    synchronized void nElementGetNativeData(long id, int[] elementData) {
+        validate();
+        rsnElementGetNativeData(mContext, id, elementData);
+    }
+    native void rsnElementGetSubElements(long con, long id,
+                                         long[] IDs, String[] names, int[] arraySizes);
+    synchronized void nElementGetSubElements(long id, long[] IDs, String[] names, int[] arraySizes) {
+        validate();
+        rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
+    }
+
+    native long rsnTypeCreate(long con, long eid, int x, int y, int z, boolean mips, boolean faces, int yuv);
+    synchronized long nTypeCreate(long eid, int x, int y, int z, boolean mips, boolean faces, int yuv) {
+        validate();
+        return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
+    }
+    native void rsnTypeGetNativeData(long con, long id, long[] typeData);
+    synchronized void nTypeGetNativeData(long id, long[] typeData) {
+        validate();
+        rsnTypeGetNativeData(mContext, id, typeData);
+    }
+
+    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, long pointer);
+    synchronized long nAllocationCreateTyped(long type, int mip, int usage, long pointer) {
+        validate();
+        return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
+    }
+
+    native long rsnAllocationCreateFromBitmap(long con, long type, int mip, Bitmap bmp,
+                int usage);
+    synchronized long nAllocationCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
+        validate();
+        return rsnAllocationCreateFromBitmap(mContext, type, mip, bmp, usage);
+    }
+
+    native long rsnAllocationCreateBitmapBackedAllocation(long con, long type, int mip, Bitmap bmp,
+                int usage);
+    synchronized long nAllocationCreateBitmapBackedAllocation(long type, int mip, Bitmap bmp,
+                int usage) {
+        validate();
+        return rsnAllocationCreateBitmapBackedAllocation(mContext, type, mip, bmp, usage);
+    }
+
+    native long rsnAllocationCubeCreateFromBitmap(long con, long type, int mip, Bitmap bmp,
+                int usage);
+    synchronized long nAllocationCubeCreateFromBitmap(long type, int mip, Bitmap bmp, int usage) {
+        validate();
+        return rsnAllocationCubeCreateFromBitmap(mContext, type, mip, bmp, usage);
+    }
+
+    native void  rsnAllocationCopyToBitmap(long con, long alloc, Bitmap bmp);
+    synchronized void nAllocationCopyToBitmap(long alloc, Bitmap bmp) {
+        validate();
+        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
+    }
+
+    native void rsnAllocationSyncAll(long con, long alloc, int src);
+    synchronized void nAllocationSyncAll(long alloc, int src) {
+        validate();
+        rsnAllocationSyncAll(mContext, alloc, src);
+    }
+
+    native ByteBuffer rsnAllocationGetByteBuffer(long con, long alloc, long[] stride,
+                int xBytesSize, int dimY, int dimZ);
+    synchronized ByteBuffer nAllocationGetByteBuffer(long alloc, long[] stride, int xBytesSize,
+                int dimY, int dimZ) {
+        validate();
+        return rsnAllocationGetByteBuffer(mContext, alloc, stride, xBytesSize, dimY, dimZ);
+    }
+
+    native void rsnAllocationSetupBufferQueue(long con, long alloc, int numAlloc);
+    synchronized void nAllocationSetupBufferQueue(long alloc, int numAlloc) {
+        validate();
+        rsnAllocationSetupBufferQueue(mContext, alloc, numAlloc);
+    }
+    native void rsnAllocationShareBufferQueue(long con, long alloc1, long alloc2);
+    synchronized void nAllocationShareBufferQueue(long alloc1, long alloc2) {
+        validate();
+        rsnAllocationShareBufferQueue(mContext, alloc1, alloc2);
+    }
+    native Surface rsnAllocationGetSurface(long con, long alloc);
+    synchronized Surface nAllocationGetSurface(long alloc) {
+        validate();
+        return rsnAllocationGetSurface(mContext, alloc);
+    }
+    native void rsnAllocationSetSurface(long con, long alloc, Surface sur);
+    synchronized void nAllocationSetSurface(long alloc, Surface sur) {
+        validate();
+        rsnAllocationSetSurface(mContext, alloc, sur);
+    }
+    native void rsnAllocationIoSend(long con, long alloc);
+    synchronized void nAllocationIoSend(long alloc) {
+        validate();
+        rsnAllocationIoSend(mContext, alloc);
+    }
+    native long rsnAllocationIoReceive(long con, long alloc);
+    synchronized long nAllocationIoReceive(long alloc) {
+        validate();
+        return rsnAllocationIoReceive(mContext, alloc);
+    }
+
+    native void rsnAllocationGenerateMipmaps(long con, long alloc);
+    synchronized void nAllocationGenerateMipmaps(long alloc) {
+        validate();
+        rsnAllocationGenerateMipmaps(mContext, alloc);
+    }
+    native void  rsnAllocationCopyFromBitmap(long con, long alloc, Bitmap bmp);
+    synchronized void nAllocationCopyFromBitmap(long alloc, Bitmap bmp) {
+        validate();
+        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
+    }
+
+
+    native void rsnAllocationData1D(long con, long id, int off, int mip, int count, Object d, int sizeBytes, int dt,
+                                    int mSize, boolean usePadding);
+    synchronized void nAllocationData1D(long id, int off, int mip, int count, Object d, int sizeBytes, Element.DataType dt,
+                                        int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID, mSize, usePadding);
+    }
+
+    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();
+        rsnAllocationElementData(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
+    }
+
+    native void rsnAllocationData2D(long con,
+                                    long dstAlloc, int dstXoff, int dstYoff,
+                                    int dstMip, int dstFace,
+                                    int width, int height,
+                                    long srcAlloc, int srcXoff, int srcYoff,
+                                    int srcMip, int srcFace);
+    synchronized void nAllocationData2D(long dstAlloc, int dstXoff, int dstYoff,
+                                        int dstMip, int dstFace,
+                                        int width, int height,
+                                        long srcAlloc, int srcXoff, int srcYoff,
+                                        int srcMip, int srcFace) {
+        validate();
+        rsnAllocationData2D(mContext,
+                            dstAlloc, dstXoff, dstYoff,
+                            dstMip, dstFace,
+                            width, height,
+                            srcAlloc, srcXoff, srcYoff,
+                            srcMip, srcFace);
+    }
+
+    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,
+                                    int mSize, boolean usePadding);
+    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face,
+                                        int w, int h, Object d, int sizeBytes, Element.DataType dt,
+                                        int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID, mSize, usePadding);
+    }
+
+    native void rsnAllocationData2D(long con, long id, int xoff, int yoff, int mip, int face, Bitmap b);
+    synchronized void nAllocationData2D(long id, int xoff, int yoff, int mip, int face, Bitmap b) {
+        validate();
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
+    }
+
+    native void rsnAllocationData3D(long con,
+                                    long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
+                                    int dstMip,
+                                    int width, int height, int depth,
+                                    long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
+                                    int srcMip);
+    synchronized void nAllocationData3D(long dstAlloc, int dstXoff, int dstYoff, int dstZoff,
+                                        int dstMip,
+                                        int width, int height, int depth,
+                                        long srcAlloc, int srcXoff, int srcYoff, int srcZoff,
+                                        int srcMip) {
+        validate();
+        rsnAllocationData3D(mContext,
+                            dstAlloc, dstXoff, dstYoff, dstZoff,
+                            dstMip, width, height, depth,
+                            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, Object d, int sizeBytes, int dt,
+                                    int mSize, boolean usePadding);
+    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,
+                                        int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationData3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes,
+                            dt.mID, mSize, usePadding);
+    }
+
+    native void rsnAllocationRead(long con, long id, Object d, int dt, int mSize, boolean usePadding);
+    synchronized void nAllocationRead(long id, Object d, Element.DataType dt, int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationRead(mContext, id, d, dt.mID, mSize, usePadding);
+    }
+
+    native void rsnAllocationRead1D(long con, long id, int off, int mip, int count, Object d,
+                                    int sizeBytes, int dt, int mSize, boolean usePadding);
+    synchronized void nAllocationRead1D(long id, int off, int mip, int count, Object d,
+                                        int sizeBytes, Element.DataType dt, int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationRead1D(mContext, id, off, mip, count, d, sizeBytes, dt.mID, mSize, usePadding);
+    }
+
+    native void rsnAllocationElementRead(long con,long id, int xoff, int yoff, int zoff,
+                                         int mip, int compIdx, byte[] d, int sizeBytes);
+    synchronized void nAllocationElementRead(long id, int xoff, int yoff, int zoff,
+                                             int mip, int compIdx, byte[] d, int sizeBytes) {
+        validate();
+        rsnAllocationElementRead(mContext, id, xoff, yoff, zoff, mip, compIdx, d, sizeBytes);
+    }
+
+    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,
+                                    int mSize, boolean usePadding);
+    synchronized void nAllocationRead2D(long id, int xoff, int yoff, int mip, int face,
+                                        int w, int h, Object d, int sizeBytes, Element.DataType dt,
+                                        int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationRead2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes, dt.mID, mSize, usePadding);
+    }
+
+    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,
+                                    int mSize, boolean usePadding);
+    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,
+                                        int mSize, boolean usePadding) {
+        validate();
+        rsnAllocationRead3D(mContext, id, xoff, yoff, zoff, mip, w, h, depth, d, sizeBytes, dt.mID, mSize, usePadding);
+    }
+
+    native long  rsnAllocationGetType(long con, long id);
+    synchronized long nAllocationGetType(long id) {
+        validate();
+        return rsnAllocationGetType(mContext, id);
+    }
+
+    native void rsnAllocationResize1D(long con, long id, int dimX);
+    synchronized void nAllocationResize1D(long id, int dimX) {
+        validate();
+        rsnAllocationResize1D(mContext, id, dimX);
+    }
+
+    native long  rsnAllocationAdapterCreate(long con, long allocId, long typeId);
+    synchronized long nAllocationAdapterCreate(long allocId, long typeId) {
+        validate();
+        return rsnAllocationAdapterCreate(mContext, allocId, typeId);
+    }
+
+    native void  rsnAllocationAdapterOffset(long con, long id, int x, int y, int z,
+                                            int mip, int face, int a1, int a2, int a3, int a4);
+    synchronized void nAllocationAdapterOffset(long id, int x, int y, int z,
+                                               int mip, int face, int a1, int a2, int a3, int a4) {
+        validate();
+        rsnAllocationAdapterOffset(mContext, id, x, y, z, mip, face, a1, a2, a3, a4);
+    }
+
+    native long rsnFileA3DCreateFromAssetStream(long con, long assetStream);
+    synchronized long nFileA3DCreateFromAssetStream(long assetStream) {
+        validate();
+        return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
+    }
+    native long rsnFileA3DCreateFromFile(long con, String path);
+    synchronized long nFileA3DCreateFromFile(String path) {
+        validate();
+        return rsnFileA3DCreateFromFile(mContext, path);
+    }
+    native long rsnFileA3DCreateFromAsset(long con, AssetManager mgr, String path);
+    synchronized long nFileA3DCreateFromAsset(AssetManager mgr, String path) {
+        validate();
+        return rsnFileA3DCreateFromAsset(mContext, mgr, path);
+    }
+    native int  rsnFileA3DGetNumIndexEntries(long con, long fileA3D);
+    synchronized int nFileA3DGetNumIndexEntries(long fileA3D) {
+        validate();
+        return rsnFileA3DGetNumIndexEntries(mContext, fileA3D);
+    }
+    native void rsnFileA3DGetIndexEntries(long con, long fileA3D, int numEntries, int[] IDs, String[] names);
+    synchronized void nFileA3DGetIndexEntries(long fileA3D, int numEntries, int[] IDs, String[] names) {
+        validate();
+        rsnFileA3DGetIndexEntries(mContext, fileA3D, numEntries, IDs, names);
+    }
+    native long rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
+    synchronized long nFileA3DGetEntryByIndex(long fileA3D, int index) {
+        validate();
+        return rsnFileA3DGetEntryByIndex(mContext, fileA3D, index);
+    }
+
+    native long rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
+    synchronized long nFontCreateFromFile(String fileName, float size, int dpi) {
+        validate();
+        return rsnFontCreateFromFile(mContext, fileName, size, dpi);
+    }
+    native long rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, long assetStream);
+    synchronized long nFontCreateFromAssetStream(String name, float size, int dpi, long assetStream) {
+        validate();
+        return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
+    }
+    native long rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
+    synchronized long nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
+        validate();
+        return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
+    }
+
+
+    native void rsnScriptBindAllocation(long con, long script, long alloc, int slot);
+    synchronized void nScriptBindAllocation(long script, long alloc, int slot) {
+        validate();
+        rsnScriptBindAllocation(mContext, script, alloc, slot);
+    }
+    native void rsnScriptSetTimeZone(long con, long script, byte[] timeZone);
+    synchronized void nScriptSetTimeZone(long script, byte[] timeZone) {
+        validate();
+        rsnScriptSetTimeZone(mContext, script, timeZone);
+    }
+    native void rsnScriptInvoke(long con, long id, int slot);
+    synchronized void nScriptInvoke(long id, int slot) {
+        validate();
+        rsnScriptInvoke(mContext, id, slot);
+    }
+
+    native void rsnScriptForEach(long con, long id, int slot, long[] ains,
+                                 long aout, byte[] params, int[] limits);
+
+    synchronized void nScriptForEach(long id, int slot, long[] ains, long aout,
+                                     byte[] params, int[] limits) {
+        validate();
+        rsnScriptForEach(mContext, id, slot, ains, aout, params, limits);
+    }
+
+    native void rsnScriptReduce(long con, long id, int slot, long[] ains,
+                                long aout, int[] limits);
+    synchronized void nScriptReduce(long id, int slot, long ains[], long aout,
+                                    int[] limits) {
+        validate();
+        rsnScriptReduce(mContext, id, slot, ains, aout, limits);
+    }
+
+    native void rsnScriptInvokeV(long con, long id, int slot, byte[] params);
+    synchronized void nScriptInvokeV(long id, int slot, byte[] params) {
+        validate();
+        rsnScriptInvokeV(mContext, id, slot, params);
+    }
+
+    native void rsnScriptSetVarI(long con, long id, int slot, int val);
+    synchronized void nScriptSetVarI(long id, int slot, int val) {
+        validate();
+        rsnScriptSetVarI(mContext, id, slot, val);
+    }
+    native int rsnScriptGetVarI(long con, long id, int slot);
+    synchronized int nScriptGetVarI(long id, int slot) {
+        validate();
+        return rsnScriptGetVarI(mContext, id, slot);
+    }
+
+    native void rsnScriptSetVarJ(long con, long id, int slot, long val);
+    synchronized void nScriptSetVarJ(long id, int slot, long val) {
+        validate();
+        rsnScriptSetVarJ(mContext, id, slot, val);
+    }
+    native long rsnScriptGetVarJ(long con, long id, int slot);
+    synchronized long nScriptGetVarJ(long id, int slot) {
+        validate();
+        return rsnScriptGetVarJ(mContext, id, slot);
+    }
+
+    native void rsnScriptSetVarF(long con, long id, int slot, float val);
+    synchronized void nScriptSetVarF(long id, int slot, float val) {
+        validate();
+        rsnScriptSetVarF(mContext, id, slot, val);
+    }
+    native float rsnScriptGetVarF(long con, long id, int slot);
+    synchronized float nScriptGetVarF(long id, int slot) {
+        validate();
+        return rsnScriptGetVarF(mContext, id, slot);
+    }
+    native void rsnScriptSetVarD(long con, long id, int slot, double val);
+    synchronized void nScriptSetVarD(long id, int slot, double val) {
+        validate();
+        rsnScriptSetVarD(mContext, id, slot, val);
+    }
+    native double rsnScriptGetVarD(long con, long id, int slot);
+    synchronized double nScriptGetVarD(long id, int slot) {
+        validate();
+        return rsnScriptGetVarD(mContext, id, slot);
+    }
+    native void rsnScriptSetVarV(long con, long id, int slot, byte[] val);
+    synchronized void nScriptSetVarV(long id, int slot, byte[] val) {
+        validate();
+        rsnScriptSetVarV(mContext, id, slot, val);
+    }
+    native void rsnScriptGetVarV(long con, long id, int slot, byte[] val);
+    synchronized void nScriptGetVarV(long id, int slot, byte[] val) {
+        validate();
+        rsnScriptGetVarV(mContext, id, slot, val);
+    }
+    native void rsnScriptSetVarVE(long con, long id, int slot, byte[] val,
+                                  long e, int[] dims);
+    synchronized void nScriptSetVarVE(long id, int slot, byte[] val,
+                                      long e, int[] dims) {
+        validate();
+        rsnScriptSetVarVE(mContext, id, slot, val, e, dims);
+    }
+    native void rsnScriptSetVarObj(long con, long id, int slot, long val);
+    synchronized void nScriptSetVarObj(long id, int slot, long val) {
+        validate();
+        rsnScriptSetVarObj(mContext, id, slot, val);
+    }
+
+    native long rsnScriptCCreate(long con, String resName, String cacheDir,
+                                 byte[] script, int length);
+    @UnsupportedAppUsage
+    synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
+        validate();
+        return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
+    }
+
+    native long rsnScriptIntrinsicCreate(long con, int id, long eid);
+    synchronized long nScriptIntrinsicCreate(int id, long eid) {
+        validate();
+        return rsnScriptIntrinsicCreate(mContext, id, eid);
+    }
+
+    native long  rsnScriptKernelIDCreate(long con, long sid, int slot, int sig);
+    synchronized long nScriptKernelIDCreate(long sid, int slot, int sig) {
+        validate();
+        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
+    }
+
+    native long  rsnScriptInvokeIDCreate(long con, long sid, int slot);
+    synchronized long nScriptInvokeIDCreate(long sid, int slot) {
+        validate();
+        return rsnScriptInvokeIDCreate(mContext, sid, slot);
+    }
+
+    native long  rsnScriptFieldIDCreate(long con, long sid, int slot);
+    synchronized long nScriptFieldIDCreate(long sid, int slot) {
+        validate();
+        return rsnScriptFieldIDCreate(mContext, sid, slot);
+    }
+
+    native long rsnScriptGroupCreate(long con, long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types);
+    synchronized long nScriptGroupCreate(long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types) {
+        validate();
+        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
+    }
+
+    native void rsnScriptGroupSetInput(long con, long group, long kernel, long alloc);
+    synchronized void nScriptGroupSetInput(long group, long kernel, long alloc) {
+        validate();
+        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
+    }
+
+    native void rsnScriptGroupSetOutput(long con, long group, long kernel, long alloc);
+    synchronized void nScriptGroupSetOutput(long group, long kernel, long alloc) {
+        validate();
+        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
+    }
+
+    native void rsnScriptGroupExecute(long con, long group);
+    synchronized void nScriptGroupExecute(long group) {
+        validate();
+        rsnScriptGroupExecute(mContext, group);
+    }
+
+    native long  rsnSamplerCreate(long con, int magFilter, int minFilter,
+                                 int wrapS, int wrapT, int wrapR, float aniso);
+    synchronized long nSamplerCreate(int magFilter, int minFilter,
+                                 int wrapS, int wrapT, int wrapR, float aniso) {
+        validate();
+        return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
+    }
+
+    native long rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
+                                      boolean depthMask, boolean dither,
+                                      int srcMode, int dstMode, int depthFunc);
+    synchronized long nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
+                                         boolean depthMask, boolean dither,
+                                         int srcMode, int dstMode, int depthFunc) {
+        validate();
+        return rsnProgramStoreCreate(mContext, r, g, b, a, depthMask, dither, srcMode,
+                                     dstMode, depthFunc);
+    }
+
+    native long rsnProgramRasterCreate(long con, boolean pointSprite, int cullMode);
+    synchronized long nProgramRasterCreate(boolean pointSprite, int cullMode) {
+        validate();
+        return rsnProgramRasterCreate(mContext, pointSprite, cullMode);
+    }
+
+    native void rsnProgramBindConstants(long con, long pv, int slot, long mID);
+    synchronized void nProgramBindConstants(long pv, int slot, long mID) {
+        validate();
+        rsnProgramBindConstants(mContext, pv, slot, mID);
+    }
+    native void rsnProgramBindTexture(long con, long vpf, int slot, long a);
+    synchronized void nProgramBindTexture(long vpf, int slot, long a) {
+        validate();
+        rsnProgramBindTexture(mContext, vpf, slot, a);
+    }
+    native void rsnProgramBindSampler(long con, long vpf, int slot, long s);
+    synchronized void nProgramBindSampler(long vpf, int slot, long s) {
+        validate();
+        rsnProgramBindSampler(mContext, vpf, slot, s);
+    }
+    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, long[] params);
+    synchronized long nProgramFragmentCreate(String shader, String[] texNames, long[] params) {
+        validate();
+        return rsnProgramFragmentCreate(mContext, shader, texNames, params);
+    }
+    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, long[] params);
+    synchronized long nProgramVertexCreate(String shader, String[] texNames, long[] params) {
+        validate();
+        return rsnProgramVertexCreate(mContext, shader, texNames, params);
+    }
+
+    native long rsnMeshCreate(long con, long[] vtx, long[] idx, int[] prim);
+    synchronized long nMeshCreate(long[] vtx, long[] idx, int[] prim) {
+        validate();
+        return rsnMeshCreate(mContext, vtx, idx, prim);
+    }
+    native int  rsnMeshGetVertexBufferCount(long con, long id);
+    synchronized int nMeshGetVertexBufferCount(long id) {
+        validate();
+        return rsnMeshGetVertexBufferCount(mContext, id);
+    }
+    native int  rsnMeshGetIndexCount(long con, long id);
+    synchronized int nMeshGetIndexCount(long id) {
+        validate();
+        return rsnMeshGetIndexCount(mContext, id);
+    }
+    native void rsnMeshGetVertices(long con, long id, long[] vtxIds, int vtxIdCount);
+    synchronized void nMeshGetVertices(long id, long[] vtxIds, int vtxIdCount) {
+        validate();
+        rsnMeshGetVertices(mContext, id, vtxIds, vtxIdCount);
+    }
+    native void rsnMeshGetIndices(long con, long id, long[] idxIds, int[] primitives, int vtxIdCount);
+    synchronized void nMeshGetIndices(long id, long[] idxIds, int[] primitives, int vtxIdCount) {
+        validate();
+        rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
+    }
+
+    native void rsnScriptIntrinsicBLAS_Single(long con, long id, int func, int TransA,
+                                              int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                              float alpha, long A, long B, float beta, long C, int incX, int incY,
+                                              int KL, int KU);
+    synchronized void nScriptIntrinsicBLAS_Single(long id, int func, int TransA,
+                                                  int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                                  float alpha, long A, long B, float beta, long C, int incX, int incY,
+                                                  int KL, int KU) {
+        validate();
+        rsnScriptIntrinsicBLAS_Single(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alpha, A, B, beta, C, incX, incY, KL, KU);
+    }
+
+    native void rsnScriptIntrinsicBLAS_Double(long con, long id, int func, int TransA,
+                                              int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                              double alpha, long A, long B, double beta, long C, int incX, int incY,
+                                              int KL, int KU);
+    synchronized void nScriptIntrinsicBLAS_Double(long id, int func, int TransA,
+                                                  int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                                  double alpha, long A, long B, double beta, long C, int incX, int incY,
+                                                  int KL, int KU) {
+        validate();
+        rsnScriptIntrinsicBLAS_Double(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alpha, A, B, beta, C, incX, incY, KL, KU);
+    }
+
+    native void rsnScriptIntrinsicBLAS_Complex(long con, long id, int func, int TransA,
+                                               int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                               float alphaX, float alphaY, long A, long B, float betaX, float betaY, long C, int incX, int incY,
+                                               int KL, int KU);
+    synchronized void nScriptIntrinsicBLAS_Complex(long id, int func, int TransA,
+                                                   int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                                   float alphaX, float alphaY, long A, long B, float betaX, float betaY, long C, int incX, int incY,
+                                                   int KL, int KU) {
+        validate();
+        rsnScriptIntrinsicBLAS_Complex(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alphaX, alphaY, A, B, betaX, betaY, C, incX, incY, KL, KU);
+    }
+
+    native void rsnScriptIntrinsicBLAS_Z(long con, long id, int func, int TransA,
+                                         int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                         double alphaX, double alphaY, long A, long B, double betaX, double betaY, long C, int incX, int incY,
+                                         int KL, int KU);
+    synchronized void nScriptIntrinsicBLAS_Z(long id, int func, int TransA,
+                                             int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+                                             double alphaX, double alphaY, long A, long B, double betaX, double betaY, long C, int incX, int incY,
+                                             int KL, int KU) {
+        validate();
+        rsnScriptIntrinsicBLAS_Z(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alphaX, alphaY, A, B, betaX, betaY, C, incX, incY, KL, KU);
+    }
+
+    native void rsnScriptIntrinsicBLAS_BNNM(long con, long id, int M, int N, int K,
+                                             long A, int a_offset, long B, int b_offset, long C, int c_offset,
+                                             int c_mult_int);
+    synchronized void nScriptIntrinsicBLAS_BNNM(long id, int M, int N, int K,
+                                             long A, int a_offset, long B, int b_offset, long C, int c_offset,
+                                             int c_mult_int) {
+        validate();
+        rsnScriptIntrinsicBLAS_BNNM(mContext, id, M, N, K, A, a_offset, B, b_offset, C, c_offset, c_mult_int);
+    }
+
+
+
+    long     mContext;
+    private boolean mDestroyed = false;
+
+    @SuppressWarnings({"FieldCanBeLocal"})
+    MessageThread mMessageThread;
+
+    volatile Element mElement_U8;
+    volatile Element mElement_I8;
+    volatile Element mElement_U16;
+    volatile Element mElement_I16;
+    volatile Element mElement_U32;
+    volatile Element mElement_I32;
+    volatile Element mElement_U64;
+    volatile Element mElement_I64;
+    volatile Element mElement_F16;
+    volatile Element mElement_F32;
+    volatile Element mElement_F64;
+    volatile Element mElement_BOOLEAN;
+
+    volatile Element mElement_ELEMENT;
+    volatile Element mElement_TYPE;
+    volatile Element mElement_ALLOCATION;
+    volatile Element mElement_SAMPLER;
+    volatile Element mElement_SCRIPT;
+    volatile Element mElement_MESH;
+    volatile Element mElement_PROGRAM_FRAGMENT;
+    volatile Element mElement_PROGRAM_VERTEX;
+    volatile Element mElement_PROGRAM_RASTER;
+    volatile Element mElement_PROGRAM_STORE;
+    volatile Element mElement_FONT;
+
+    volatile Element mElement_A_8;
+    volatile Element mElement_RGB_565;
+    volatile Element mElement_RGB_888;
+    volatile Element mElement_RGBA_5551;
+    volatile Element mElement_RGBA_4444;
+    volatile Element mElement_RGBA_8888;
+
+    volatile Element mElement_HALF_2;
+    volatile Element mElement_HALF_3;
+    volatile Element mElement_HALF_4;
+
+    volatile Element mElement_FLOAT_2;
+    volatile Element mElement_FLOAT_3;
+    volatile Element mElement_FLOAT_4;
+
+    volatile Element mElement_DOUBLE_2;
+    volatile Element mElement_DOUBLE_3;
+    volatile Element mElement_DOUBLE_4;
+
+    volatile Element mElement_UCHAR_2;
+    volatile Element mElement_UCHAR_3;
+    volatile Element mElement_UCHAR_4;
+
+    volatile Element mElement_CHAR_2;
+    volatile Element mElement_CHAR_3;
+    volatile Element mElement_CHAR_4;
+
+    volatile Element mElement_USHORT_2;
+    volatile Element mElement_USHORT_3;
+    volatile Element mElement_USHORT_4;
+
+    volatile Element mElement_SHORT_2;
+    volatile Element mElement_SHORT_3;
+    volatile Element mElement_SHORT_4;
+
+    volatile Element mElement_UINT_2;
+    volatile Element mElement_UINT_3;
+    volatile Element mElement_UINT_4;
+
+    volatile Element mElement_INT_2;
+    volatile Element mElement_INT_3;
+    volatile Element mElement_INT_4;
+
+    volatile Element mElement_ULONG_2;
+    volatile Element mElement_ULONG_3;
+    volatile Element mElement_ULONG_4;
+
+    volatile Element mElement_LONG_2;
+    volatile Element mElement_LONG_3;
+    volatile Element mElement_LONG_4;
+
+    volatile Element mElement_YUV;
+
+    volatile Element mElement_MATRIX_4X4;
+    volatile Element mElement_MATRIX_3X3;
+    volatile Element mElement_MATRIX_2X2;
+
+    volatile Sampler mSampler_CLAMP_NEAREST;
+    volatile Sampler mSampler_CLAMP_LINEAR;
+    volatile Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
+    volatile Sampler mSampler_WRAP_NEAREST;
+    volatile Sampler mSampler_WRAP_LINEAR;
+    volatile Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
+    volatile Sampler mSampler_MIRRORED_REPEAT_NEAREST;
+    volatile Sampler mSampler_MIRRORED_REPEAT_LINEAR;
+    volatile Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
+
+    ProgramStore mProgramStore_BLEND_NONE_DEPTH_TEST;
+    ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
+    ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_TEST;
+    ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
+
+    ProgramRaster mProgramRaster_CULL_BACK;
+    ProgramRaster mProgramRaster_CULL_FRONT;
+    ProgramRaster mProgramRaster_CULL_NONE;
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+
+    /**
+     * The base class from which an application should derive in order
+     * to receive RS messages from scripts. When a script calls {@code
+     * rsSendToClient}, the data fields will be filled, and the run
+     * method will be called on a separate thread.  This will occur
+     * some time after {@code rsSendToClient} completes in the script,
+     * as {@code rsSendToClient} is asynchronous. Message handlers are
+     * not guaranteed to have completed when {@link
+     * android.renderscript.RenderScript#finish} returns.
+     *
+     */
+    public static class RSMessageHandler implements Runnable {
+        protected int[] mData;
+        protected int mID;
+        protected int mLength;
+        public void run() {
+        }
+    }
+    /**
+     * If an application is expecting messages, it should set this
+     * field to an instance of {@link RSMessageHandler}.  This
+     * instance will receive all the user messages sent from {@code
+     * sendToClient} by scripts from this context.
+     *
+     */
+    @UnsupportedAppUsage
+    RSMessageHandler mMessageCallback = null;
+
+    public void setMessageHandler(RSMessageHandler msg) {
+        mMessageCallback = msg;
+    }
+    public RSMessageHandler getMessageHandler() {
+        return mMessageCallback;
+    }
+
+    /**
+     * Place a message into the message queue to be sent back to the message
+     * handler once all previous commands have been executed.
+     *
+     * @param id
+     * @param data
+     */
+    public void sendMessage(int id, int[] data) {
+        nContextSendMessage(id, data);
+    }
+
+    /**
+     * The runtime error handler base class.  An application should derive from this class
+     * if it wishes to install an error handler.  When errors occur at runtime,
+     * the fields in this class will be filled, and the run method will be called.
+     *
+     */
+    public static class RSErrorHandler implements Runnable {
+        protected String mErrorMessage;
+        protected int mErrorNum;
+        public void run() {
+        }
+    }
+
+    /**
+     * Application Error handler.  All runtime errors will be dispatched to the
+     * instance of RSAsyncError set here.  If this field is null a
+     * {@link RSRuntimeException} will instead be thrown with details about the error.
+     * This will cause program termaination.
+     *
+     */
+    RSErrorHandler mErrorCallback = null;
+
+    public void setErrorHandler(RSErrorHandler msg) {
+        mErrorCallback = msg;
+    }
+    public RSErrorHandler getErrorHandler() {
+        return mErrorCallback;
+    }
+
+    /**
+     * RenderScript worker thread priority enumeration.  The default value is
+     * NORMAL.  Applications wishing to do background processing should set
+     * their priority to LOW to avoid starving forground processes.
+     */
+    public enum Priority {
+        // These values used to represent official thread priority values
+        // now they are simply enums to be used by the runtime side
+        LOW (15),
+        NORMAL (-8);
+
+        int mID;
+        Priority(int id) {
+            mID = id;
+        }
+    }
+
+    void validateObject(BaseObj o) {
+        if (o != null) {
+            if (o.mRS != this) {
+                throw new RSIllegalArgumentException("Attempting to use an object across contexts.");
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+    void validate() {
+        if (mContext == 0) {
+            throw new RSInvalidStateException("Calling RS with no Context active.");
+        }
+    }
+
+
+    /**
+     * Change the priority of the worker threads for this context.
+     *
+     * @param p New priority to be set.
+     */
+    public void setPriority(Priority p) {
+        validate();
+        nContextSetPriority(p.mID);
+    }
+
+    static class MessageThread extends Thread {
+        RenderScript mRS;
+        boolean mRun = true;
+        int[] mAuxData = new int[2];
+
+        static final int RS_MESSAGE_TO_CLIENT_NONE = 0;
+        static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1;
+        static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2;
+        static final int RS_MESSAGE_TO_CLIENT_ERROR = 3;
+        static final int RS_MESSAGE_TO_CLIENT_USER = 4;
+        static final int RS_MESSAGE_TO_CLIENT_NEW_BUFFER = 5;
+
+        static final int RS_ERROR_FATAL_DEBUG = 0x0800;
+        static final int RS_ERROR_FATAL_UNKNOWN = 0x1000;
+
+        MessageThread(RenderScript rs) {
+            super("RSMessageThread");
+            mRS = rs;
+
+        }
+
+        public void run() {
+            // This function is a temporary solution.  The final solution will
+            // used typed allocations where the message id is the type indicator.
+            int[] rbuf = new int[16];
+            mRS.nContextInitToClient(mRS.mContext);
+            while(mRun) {
+                rbuf[0] = 0;
+                int msg = mRS.nContextPeekMessage(mRS.mContext, mAuxData);
+                int size = mAuxData[1];
+                int subID = mAuxData[0];
+
+                if (msg == RS_MESSAGE_TO_CLIENT_USER) {
+                    if ((size>>2) >= rbuf.length) {
+                        rbuf = new int[(size + 3) >> 2];
+                    }
+                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
+                        RS_MESSAGE_TO_CLIENT_USER) {
+                        throw new RSDriverException("Error processing message from RenderScript.");
+                    }
+
+                    if(mRS.mMessageCallback != null) {
+                        mRS.mMessageCallback.mData = rbuf;
+                        mRS.mMessageCallback.mID = subID;
+                        mRS.mMessageCallback.mLength = size;
+                        mRS.mMessageCallback.run();
+                    } else {
+                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
+                    }
+                    continue;
+                }
+
+                if (msg == RS_MESSAGE_TO_CLIENT_ERROR) {
+                    String e = mRS.nContextGetErrorMessage(mRS.mContext);
+
+                    // Throw RSRuntimeException under the following conditions:
+                    //
+                    // 1) It is an unknown fatal error.
+                    // 2) It is a debug fatal error, and we are not in a
+                    //    debug context.
+                    // 3) It is a debug fatal error, and we do not have an
+                    //    error callback.
+                    if (subID >= RS_ERROR_FATAL_UNKNOWN ||
+                        (subID >= RS_ERROR_FATAL_DEBUG &&
+                         (mRS.mContextType != ContextType.DEBUG ||
+                          mRS.mErrorCallback == null))) {
+                        throw new RSRuntimeException("Fatal error " + subID + ", details: " + e);
+                    }
+
+                    if(mRS.mErrorCallback != null) {
+                        mRS.mErrorCallback.mErrorMessage = e;
+                        mRS.mErrorCallback.mErrorNum = subID;
+                        mRS.mErrorCallback.run();
+                    } else {
+                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
+                        // Do not throw here. In these cases, we do not have
+                        // a fatal error.
+                    }
+                    continue;
+                }
+
+                if (msg == RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
+                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
+                        RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
+                        throw new RSDriverException("Error processing message from RenderScript.");
+                    }
+                    long bufferID = ((long)rbuf[1] << 32L) + ((long)rbuf[0] & 0xffffffffL);
+                    Allocation.sendBufferNotification(bufferID);
+                    continue;
+                }
+
+                // 2: teardown.
+                // But we want to avoid starving other threads during
+                // teardown by yielding until the next line in the destructor
+                // can execute to set mRun = false
+                try {
+                    sleep(1, 0);
+                } catch(InterruptedException e) {
+                }
+            }
+            //Log.d(LOG_TAG, "MessageThread exiting.");
+        }
+    }
+
+    RenderScript(Context ctx) {
+        mContextType = ContextType.NORMAL;
+        if (ctx != null) {
+            mApplicationContext = ctx.getApplicationContext();
+        }
+        mRWLock = new ReentrantReadWriteLock();
+    }
+
+    /**
+     * Gets the application context associated with the RenderScript context.
+     *
+     * @return The application context.
+     */
+    public final Context getApplicationContext() {
+        return mApplicationContext;
+    }
+
+    /**
+     * Name of the file that holds the object cache.
+     */
+    private static String mCachePath;
+
+    /**
+     * Gets the path to the code cache.
+     */
+    static synchronized String getCachePath() {
+        if (mCachePath == null) {
+            final String CACHE_PATH = "com.android.renderscript.cache";
+            if (RenderScriptCacheDir.mCacheDir == null) {
+                throw new RSRuntimeException("RenderScript code cache directory uninitialized.");
+            }
+            File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
+            mCachePath = f.getAbsolutePath();
+            f.mkdirs();
+        }
+        return mCachePath;
+    }
+
+    /**
+     * Create a RenderScript context.
+     *
+     * @param ctx The context.
+     * @return RenderScript
+     */
+    private static RenderScript internalCreate(Context ctx, int sdkVersion, ContextType ct, int flags) {
+        if (!sInitialized) {
+            Log.e(LOG_TAG, "RenderScript.create() called when disabled; someone is likely to crash");
+            return null;
+        }
+
+        if ((flags & ~(CREATE_FLAG_LOW_LATENCY | CREATE_FLAG_LOW_POWER |
+                       CREATE_FLAG_WAIT_FOR_ATTACH)) != 0) {
+            throw new RSIllegalArgumentException("Invalid flags passed.");
+        }
+
+        RenderScript rs = new RenderScript(ctx);
+
+        long device = rs.nDeviceCreate();
+        rs.mContext = rs.nContextCreate(device, flags, sdkVersion, ct.mID);
+        rs.mContextType = ct;
+        rs.mContextFlags = flags;
+        rs.mContextSdkVersion = sdkVersion;
+        if (rs.mContext == 0) {
+            throw new RSDriverException("Failed to create RS context.");
+        }
+
+        // set up cache directory for entire context
+        rs.nContextSetCacheDir(RenderScript.getCachePath());
+
+        rs.mMessageThread = new MessageThread(rs);
+        rs.mMessageThread.start();
+        return rs;
+    }
+
+    /**
+     * calls create(ctx, ContextType.NORMAL, CREATE_FLAG_NONE)
+     *
+     * See documentation for @create for details
+     *
+     * @param ctx The context.
+     * @return RenderScript
+     */
+    public static RenderScript create(Context ctx) {
+        return create(ctx, ContextType.NORMAL);
+    }
+
+    /**
+     * calls create(ctx, ct, CREATE_FLAG_NONE)
+     *
+     * See documentation for @create for details
+     *
+     * @param ctx The context.
+     * @param ct The type of context to be created.
+     * @return RenderScript
+     */
+    public static RenderScript create(Context ctx, ContextType ct) {
+        return create(ctx, ct, CREATE_FLAG_NONE);
+    }
+
+
+    /**
+     * Gets or creates a RenderScript context of the specified type.
+     *
+     * The returned context will be cached for future reuse within
+     * the process. When an application is finished using
+     * RenderScript it should call releaseAllContexts()
+     *
+     * A process context is a context designed for easy creation and
+     * lifecycle management.  Multiple calls to this function will
+     * return the same object provided they are called with the same
+     * options.  This allows it to be used any time a RenderScript
+     * context is needed.
+     *
+     * Prior to API 23 this always created a new context.
+     *
+     * @param ctx The context.
+     * @param ct The type of context to be created.
+     * @param flags The OR of the CREATE_FLAG_* options desired
+     * @return RenderScript
+     */
+    public static RenderScript create(Context ctx, ContextType ct, int flags) {
+        int v = ctx.getApplicationInfo().targetSdkVersion;
+        return create(ctx, v, ct, flags);
+    }
+
+    /**
+     * calls create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE)
+     *
+     * Used by the RenderScriptThunker to maintain backward compatibility.
+     *
+     * @hide
+     * @param ctx The context.
+     * @param sdkVersion The target SDK Version.
+     * @return RenderScript
+     */
+    @UnsupportedAppUsage
+    public static RenderScript create(Context ctx, int sdkVersion) {
+        return create(ctx, sdkVersion, ContextType.NORMAL, CREATE_FLAG_NONE);
+    }
+
+     /**
+     * Gets or creates a RenderScript context of the specified type.
+     *
+     * @param ctx The context.
+     * @param ct The type of context to be created.
+     * @param sdkVersion The target SDK Version.
+     * @param flags The OR of the CREATE_FLAG_* options desired
+     * @return RenderScript
+     */
+    @UnsupportedAppUsage
+    private static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
+        if (sdkVersion < 23) {
+            return internalCreate(ctx, sdkVersion, ct, flags);
+        }
+
+        synchronized (mProcessContextList) {
+            for (RenderScript prs : mProcessContextList) {
+                if ((prs.mContextType == ct) &&
+                    (prs.mContextFlags == flags) &&
+                    (prs.mContextSdkVersion == sdkVersion)) {
+
+                    return prs;
+                }
+            }
+
+            RenderScript prs = internalCreate(ctx, sdkVersion, ct, flags);
+            prs.mIsProcessContext = true;
+            mProcessContextList.add(prs);
+            return prs;
+        }
+    }
+
+    /**
+     * Releases all the process contexts.  This is the same as
+     * calling .destroy() on each unique context retreived with
+     * create(...). If no contexts have been created this
+     * function does nothing.
+     *
+     * Typically you call this when your application is losing focus
+     * and will not be using a context for some time.
+     *
+     * This has no effect on a context created with
+     * createMultiContext()
+     */
+    public static void releaseAllContexts() {
+        ArrayList<RenderScript> oldList;
+        synchronized (mProcessContextList) {
+            oldList = mProcessContextList;
+            mProcessContextList = new ArrayList<RenderScript>();
+        }
+
+        for (RenderScript prs : oldList) {
+            prs.mIsProcessContext = false;
+            prs.destroy();
+        }
+        oldList.clear();
+    }
+
+
+
+    /**
+     * Create a RenderScript context.
+     *
+     * This is an advanced function intended for applications which
+     * need to create more than one RenderScript context to be used
+     * at the same time.
+     *
+     * If you need a single context please use create()
+     *
+     * @param ctx The context.
+     * @return RenderScript
+     */
+    public static RenderScript createMultiContext(Context ctx, ContextType ct, int flags, int API_number) {
+        return internalCreate(ctx, API_number, ct, flags);
+    }
+
+
+    /**
+     * Print the currently available debugging information about the state of
+     * the RS context to the log.
+     *
+     */
+    public void contextDump() {
+        validate();
+        nContextDump(0);
+    }
+
+    /**
+     * Wait for any pending asynchronous opeations (such as copies to a RS
+     * allocation or RS script executions) to complete.
+     *
+     */
+    public void finish() {
+        nContextFinish();
+    }
+
+    private void helpDestroy() {
+        boolean shouldDestroy = false;
+        synchronized(this) {
+            if (!mDestroyed) {
+                shouldDestroy = true;
+                mDestroyed = true;
+            }
+        }
+
+        if (shouldDestroy) {
+            nContextFinish();
+
+            nContextDeinitToClient(mContext);
+            mMessageThread.mRun = false;
+            // Interrupt mMessageThread so it gets to see immediately that mRun is false
+            // and exit rightaway.
+            mMessageThread.interrupt();
+
+            // Wait for mMessageThread to join.  Try in a loop, in case this thread gets interrupted
+            // during the wait.  If interrupted, set the "interrupted" status of the current thread.
+            boolean hasJoined = false, interrupted = false;
+            while (!hasJoined) {
+                try {
+                    mMessageThread.join();
+                    hasJoined = true;
+                } catch (InterruptedException e) {
+                    interrupted = true;
+                }
+            }
+            if (interrupted) {
+                Log.v(LOG_TAG, "Interrupted during wait for MessageThread to join");
+                Thread.currentThread().interrupt();
+            }
+
+            nContextDestroy();
+        }
+    }
+
+    protected void finalize() throws Throwable {
+        helpDestroy();
+        super.finalize();
+    }
+
+
+    /**
+     * Destroys this RenderScript context.  Once this function is called,
+     * using this context or any objects belonging to this context is
+     * illegal.
+     *
+     * API 23+, this function is a NOP if the context was created
+     * with create().  Please use releaseAllContexts() to clean up
+     * contexts created with the create function.
+     *
+     */
+    public void destroy() {
+        if (mIsProcessContext) {
+            // users cannot destroy a process context
+            return;
+        }
+        validate();
+        helpDestroy();
+    }
+
+    boolean isAlive() {
+        return mContext != 0;
+    }
+
+    long safeID(BaseObj o) {
+        if(o != null) {
+            return o.getID(this);
+        }
+        return 0;
+    }
+}
diff --git a/android/renderscript/RenderScriptCacheDir.java b/android/renderscript/RenderScriptCacheDir.java
new file mode 100644
index 0000000..cd6e8b1
--- /dev/null
+++ b/android/renderscript/RenderScriptCacheDir.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008-2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+import java.io.File;
+
+/**
+ * Used only for tracking the RenderScript cache directory.
+ * @hide
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class RenderScriptCacheDir {
+     /**
+     * Sets the directory to use as a persistent storage for the
+     * renderscript object file cache.
+     *
+     * @hide
+     * @param cacheDir A directory the current process can write to
+     */
+    @UnsupportedAppUsage
+    public static void setupDiskCache(File cacheDir) {
+        // Defer creation of cache path to nScriptCCreate().
+        mCacheDir = cacheDir;
+    }
+
+    @UnsupportedAppUsage
+    static File mCacheDir;
+
+}
diff --git a/android/renderscript/RenderScriptGL.java b/android/renderscript/RenderScriptGL.java
new file mode 100644
index 0000000..d46dbf6
--- /dev/null
+++ b/android/renderscript/RenderScriptGL.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+
+/**
+ * @hide
+ * @deprecated in API 16
+ * The Graphics derivitive of RenderScript.  Extends the basic context to add a
+ * root script which is the display window for graphical output.  When the
+ * system needs to update the display the currently bound root script will be
+ * called.  This script is expected to issue the rendering commands to repaint
+ * the screen.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ **/
+@Deprecated
+public class RenderScriptGL extends RenderScript {
+    int mWidth;
+    int mHeight;
+
+    /**
+     * @deprecated in API 16
+     * Class which is used to describe a pixel format for a graphical buffer.
+     * This is used to describe the intended format of the display surface.
+     *
+     * The configuration is described by pairs of minimum and preferred bit
+     * depths for each component within the config and additional structural
+     * information.
+     */
+    public static class SurfaceConfig {
+        int mDepthMin       = 0;
+        int mDepthPref      = 0;
+        int mStencilMin     = 0;
+        int mStencilPref    = 0;
+        int mColorMin       = 8;
+        int mColorPref      = 8;
+        int mAlphaMin       = 0;
+        int mAlphaPref      = 0;
+        int mSamplesMin     = 1;
+        int mSamplesPref    = 1;
+        float mSamplesQ     = 1.f;
+
+        /**
+         * @deprecated in API 16
+         */
+        @UnsupportedAppUsage
+        public SurfaceConfig() {
+        }
+
+        /**
+         * @deprecated in API 16
+         */
+        public SurfaceConfig(SurfaceConfig sc) {
+            mDepthMin = sc.mDepthMin;
+            mDepthPref = sc.mDepthPref;
+            mStencilMin = sc.mStencilMin;
+            mStencilPref = sc.mStencilPref;
+            mColorMin = sc.mColorMin;
+            mColorPref = sc.mColorPref;
+            mAlphaMin = sc.mAlphaMin;
+            mAlphaPref = sc.mAlphaPref;
+            mSamplesMin = sc.mSamplesMin;
+            mSamplesPref = sc.mSamplesPref;
+            mSamplesQ = sc.mSamplesQ;
+        }
+
+        private void validateRange(int umin, int upref, int rmin, int rmax) {
+            if (umin < rmin || umin > rmax) {
+                throw new RSIllegalArgumentException("Minimum value provided out of range.");
+            }
+            if (upref < umin) {
+                throw new RSIllegalArgumentException("preferred must be >= Minimum.");
+            }
+        }
+
+        /**
+         * @deprecated in API 16
+         * Set the per-component bit depth for color (red, green, blue).  This
+         * configures the surface for an unsigned integer buffer type.
+         *
+         * @param minimum
+         * @param preferred
+         */
+        public void setColor(int minimum, int preferred) {
+            validateRange(minimum, preferred, 5, 8);
+            mColorMin = minimum;
+            mColorPref = preferred;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Set the bit depth for alpha. This configures the surface for
+         * an unsigned integer buffer type.
+         *
+         * @param minimum
+         * @param preferred
+         */
+        public void setAlpha(int minimum, int preferred) {
+            validateRange(minimum, preferred, 0, 8);
+            mAlphaMin = minimum;
+            mAlphaPref = preferred;
+        }
+
+         /**
+         * @deprecated in API 16
+         * Set the bit depth for the depth buffer. This configures the
+         * surface for an unsigned integer buffer type.  If a minimum of 0
+         * is specified then its possible no depth buffer will be
+         * allocated.
+         *
+         * @param minimum
+         * @param preferred
+         */
+        @UnsupportedAppUsage
+        public void setDepth(int minimum, int preferred) {
+            validateRange(minimum, preferred, 0, 24);
+            mDepthMin = minimum;
+            mDepthPref = preferred;
+        }
+
+        /**
+         * @deprecated in API 16
+         * Configure the multisample rendering.
+         *
+         * @param minimum The required number of samples, must be at least 1.
+         * @param preferred The targe number of samples, must be at least
+         *                  minimum
+         * @param Q  The quality of samples, range 0-1.  Used to decide between
+         *           different formats which have the same number of samples but
+         *           different rendering quality.
+         */
+        public void setSamples(int minimum, int preferred, float Q) {
+            validateRange(minimum, preferred, 1, 32);
+            if (Q < 0.0f || Q > 1.0f) {
+                throw new RSIllegalArgumentException("Quality out of 0-1 range.");
+            }
+            mSamplesMin = minimum;
+            mSamplesPref = preferred;
+            mSamplesQ = Q;
+        }
+    };
+
+    SurfaceConfig mSurfaceConfig;
+
+    /**
+     * @deprecated in API 16
+     * Construct a new RenderScriptGL context.
+     *
+     * @param ctx The context.
+     * @param sc The desired format of the primary rendering surface.
+     */
+    @UnsupportedAppUsage
+    public RenderScriptGL(Context ctx, SurfaceConfig sc) {
+        super(ctx);
+        mSurfaceConfig = new SurfaceConfig(sc);
+
+        int sdkVersion = ctx.getApplicationInfo().targetSdkVersion;
+
+        mWidth = 0;
+        mHeight = 0;
+        long device = nDeviceCreate();
+        int dpi = ctx.getResources().getDisplayMetrics().densityDpi;
+        mContext = nContextCreateGL(device, 0, sdkVersion,
+                                    mSurfaceConfig.mColorMin, mSurfaceConfig.mColorPref,
+                                    mSurfaceConfig.mAlphaMin, mSurfaceConfig.mAlphaPref,
+                                    mSurfaceConfig.mDepthMin, mSurfaceConfig.mDepthPref,
+                                    mSurfaceConfig.mStencilMin, mSurfaceConfig.mStencilPref,
+                                    mSurfaceConfig.mSamplesMin, mSurfaceConfig.mSamplesPref,
+                                    mSurfaceConfig.mSamplesQ, dpi);
+        if (mContext == 0) {
+            throw new RSDriverException("Failed to create RS context.");
+        }
+        mMessageThread = new MessageThread(this);
+        mMessageThread.start();
+    }
+
+    /**
+     * @deprecated in API 16
+     * Bind an os surface
+     *
+     *
+     * @param w
+     * @param h
+     * @param sur
+     */
+    @UnsupportedAppUsage
+    public void setSurface(SurfaceHolder sur, int w, int h) {
+        validate();
+        Surface s = null;
+        if (sur != null) {
+            s = sur.getSurface();
+        }
+        mWidth = w;
+        mHeight = h;
+        nContextSetSurface(w, h, s);
+    }
+
+    /**
+     * @deprecated in API 16
+     * Bind an os surface
+     *
+     * @param w
+     * @param h
+     * @param sur
+     */
+    public void setSurfaceTexture(SurfaceTexture sur, int w, int h) {
+        validate();
+        //android.util.Log.v("rs", "set surface " + sur + " w=" + w + ", h=" + h);
+
+        Surface s = null;
+        if (sur != null) {
+            s = new Surface(sur);
+        }
+        mWidth = w;
+        mHeight = h;
+        nContextSetSurface(w, h, s);
+    }
+
+    /**
+     * @deprecated in API 16
+     * return the height of the last set surface.
+     *
+     * @return int
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * @deprecated in API 16
+     * return the width of the last set surface.
+     *
+     * @return int
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * @deprecated in API 16
+     * Temporarly halt calls to the root rendering script.
+     *
+     */
+    public void pause() {
+        validate();
+        nContextPause();
+    }
+
+    /**
+     * @deprecated in API 16
+     * Resume calls to the root rendering script.
+     *
+     */
+    public void resume() {
+        validate();
+        nContextResume();
+    }
+
+
+    /**
+     * @deprecated in API 16
+     * Set the script to handle calls to render the primary surface.
+     *
+     * @param s Graphics script to process rendering requests.
+     */
+    @UnsupportedAppUsage
+    public void bindRootScript(Script s) {
+        validate();
+        nContextBindRootScript((int)safeID(s));
+    }
+
+    /**
+     * @deprecated in API 16
+     * Set the default ProgramStore object seen as the parent state by the root
+     * rendering script.
+     *
+     * @param p
+     */
+    @UnsupportedAppUsage
+    public void bindProgramStore(ProgramStore p) {
+        validate();
+        nContextBindProgramStore((int)safeID(p));
+    }
+
+    /**
+     * @deprecated in API 16
+     * Set the default ProgramFragment object seen as the parent state by the
+     * root rendering script.
+     *
+     * @param p
+     */
+    public void bindProgramFragment(ProgramFragment p) {
+        validate();
+        nContextBindProgramFragment((int)safeID(p));
+    }
+
+    /**
+     * @deprecated in API 16
+     * Set the default ProgramRaster object seen as the parent state by the
+     * root rendering script.
+     *
+     * @param p
+     */
+    @UnsupportedAppUsage
+    public void bindProgramRaster(ProgramRaster p) {
+        validate();
+        nContextBindProgramRaster((int)safeID(p));
+    }
+
+    /**
+     * @deprecated in API 16
+     * Set the default ProgramVertex object seen as the parent state by the
+     * root rendering script.
+     *
+     * @param p
+     */
+    @UnsupportedAppUsage
+    public void bindProgramVertex(ProgramVertex p) {
+        validate();
+        nContextBindProgramVertex((int)safeID(p));
+    }
+
+}
diff --git a/android/renderscript/Sampler.java b/android/renderscript/Sampler.java
new file mode 100644
index 0000000..06f036d
--- /dev/null
+++ b/android/renderscript/Sampler.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Sampler object that defines how Allocations can be read as textures within a
+ * kernel. Samplers are used in conjunction with the {@code rsSample} runtime
+ * function to return values from normalized coordinates.
+ *
+ * Any Allocation used with a Sampler must have been created with {@link
+ * android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE}; using a Sampler on
+ * an {@link android.renderscript.Allocation} that was not created with {@link
+ * android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE} is undefined.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Sampler extends BaseObj {
+    public enum Value {
+        NEAREST (0),
+        LINEAR (1),
+        LINEAR_MIP_LINEAR (2),
+        LINEAR_MIP_NEAREST (5),
+        WRAP (3),
+        CLAMP (4),
+        MIRRORED_REPEAT (6);
+
+        int mID;
+        Value(int id) {
+            mID = id;
+        }
+    }
+
+    Value mMin;
+    Value mMag;
+    Value mWrapS;
+    Value mWrapT;
+    Value mWrapR;
+    float mAniso;
+
+    Sampler(long id, RenderScript rs) {
+        super(id, rs);
+        guard.open("destroy");
+    }
+
+    /**
+     * @return minification setting for the sampler
+     */
+    public Value getMinification() {
+        return mMin;
+    }
+
+    /**
+     * @return magnification setting for the sampler
+     */
+    public Value getMagnification() {
+        return mMag;
+    }
+
+    /**
+     * @return S wrapping mode for the sampler
+     */
+    public Value getWrapS() {
+        return mWrapS;
+    }
+
+    /**
+     * @return T wrapping mode for the sampler
+     */
+    public Value getWrapT() {
+        return mWrapT;
+    }
+
+    /**
+     * @return anisotropy setting for the sampler
+     */
+    public float getAnisotropy() {
+        return mAniso;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to nearest and wrap modes set to
+     * clamp.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler CLAMP_NEAREST(RenderScript rs) {
+        if (rs.mSampler_CLAMP_NEAREST == null) {
+            synchronized (rs) {
+                if (rs.mSampler_CLAMP_NEAREST == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.NEAREST);
+                    b.setMagnification(Value.NEAREST);
+                    b.setWrapS(Value.CLAMP);
+                    b.setWrapT(Value.CLAMP);
+                    rs.mSampler_CLAMP_NEAREST = b.create();
+                }
+            }
+        }
+        return rs.mSampler_CLAMP_NEAREST;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to linear and wrap modes set to
+     * clamp.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler CLAMP_LINEAR(RenderScript rs) {
+        if (rs.mSampler_CLAMP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_CLAMP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.CLAMP);
+                    b.setWrapT(Value.CLAMP);
+                    rs.mSampler_CLAMP_LINEAR = b.create();
+                }
+            }
+        }
+        return rs.mSampler_CLAMP_LINEAR;
+    }
+
+    /**
+     * Retrieve a sampler with mag set to linear, min linear mipmap linear, and
+     * wrap modes set to clamp.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler CLAMP_LINEAR_MIP_LINEAR(RenderScript rs) {
+        if (rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR_MIP_LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.CLAMP);
+                    b.setWrapT(Value.CLAMP);
+                    rs.mSampler_CLAMP_LINEAR_MIP_LINEAR = b.create();
+                }
+            }
+        }
+        return rs.mSampler_CLAMP_LINEAR_MIP_LINEAR;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to nearest and wrap modes set to
+     * wrap.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler WRAP_NEAREST(RenderScript rs) {
+        if (rs.mSampler_WRAP_NEAREST == null) {
+            synchronized (rs) {
+                if (rs.mSampler_WRAP_NEAREST == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.NEAREST);
+                    b.setMagnification(Value.NEAREST);
+                    b.setWrapS(Value.WRAP);
+                    b.setWrapT(Value.WRAP);
+                    rs.mSampler_WRAP_NEAREST = b.create();
+                }
+            }
+        }
+        return rs.mSampler_WRAP_NEAREST;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to linear and wrap modes set to
+     * wrap.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler WRAP_LINEAR(RenderScript rs) {
+        if (rs.mSampler_WRAP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_WRAP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.WRAP);
+                    b.setWrapT(Value.WRAP);
+                    rs.mSampler_WRAP_LINEAR = b.create();
+                }
+            }
+        }
+        return rs.mSampler_WRAP_LINEAR;
+    }
+
+    /**
+     * Retrieve a sampler with mag set to linear, min linear mipmap linear, and
+     * wrap modes set to wrap.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler WRAP_LINEAR_MIP_LINEAR(RenderScript rs) {
+        if (rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR_MIP_LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.WRAP);
+                    b.setWrapT(Value.WRAP);
+                    rs.mSampler_WRAP_LINEAR_MIP_LINEAR = b.create();
+                }
+            }
+        }
+        return rs.mSampler_WRAP_LINEAR_MIP_LINEAR;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to nearest and wrap modes set to
+     * mirrored repeat.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler MIRRORED_REPEAT_NEAREST(RenderScript rs) {
+        if (rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
+            synchronized (rs) {
+                if (rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.NEAREST);
+                    b.setMagnification(Value.NEAREST);
+                    b.setWrapS(Value.MIRRORED_REPEAT);
+                    b.setWrapT(Value.MIRRORED_REPEAT);
+                    rs.mSampler_MIRRORED_REPEAT_NEAREST = b.create();
+                }
+            }
+        }
+        return rs.mSampler_MIRRORED_REPEAT_NEAREST;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to linear and wrap modes set to
+     * mirrored repeat.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler MIRRORED_REPEAT_LINEAR(RenderScript rs) {
+        if (rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.MIRRORED_REPEAT);
+                    b.setWrapT(Value.MIRRORED_REPEAT);
+                    rs.mSampler_MIRRORED_REPEAT_LINEAR = b.create();
+                }
+            }
+        }
+        return rs.mSampler_MIRRORED_REPEAT_LINEAR;
+    }
+
+    /**
+     * Retrieve a sampler with min and mag set to linear and wrap modes set to
+     * mirrored repeat.
+     *
+     * @param rs Context to which the sampler will belong.
+     *
+     * @return Sampler
+     */
+    public static Sampler MIRRORED_REPEAT_LINEAR_MIP_LINEAR(RenderScript rs) {
+        if (rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR_MIP_LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.MIRRORED_REPEAT);
+                    b.setWrapT(Value.MIRRORED_REPEAT);
+                    rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR = b.create();
+                }
+            }
+        }
+        return rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
+    }
+
+    /**
+     * Builder for creating non-standard samplers.  This is only necessary if
+     * a Sampler with different min and mag modes is desired.
+     */
+    public static class Builder {
+        RenderScript mRS;
+        Value mMin;
+        Value mMag;
+        Value mWrapS;
+        Value mWrapT;
+        Value mWrapR;
+        float mAniso;
+
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mMin = Value.NEAREST;
+            mMag = Value.NEAREST;
+            mWrapS = Value.WRAP;
+            mWrapT = Value.WRAP;
+            mWrapR = Value.WRAP;
+            mAniso = 1.0f;
+        }
+
+        public void setMinification(Value v) {
+            if (v == Value.NEAREST ||
+                v == Value.LINEAR ||
+                v == Value.LINEAR_MIP_LINEAR ||
+                v == Value.LINEAR_MIP_NEAREST) {
+                mMin = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
+        }
+
+        public void setMagnification(Value v) {
+            if (v == Value.NEAREST || v == Value.LINEAR) {
+                mMag = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
+        }
+
+        public void setWrapS(Value v) {
+            if (v == Value.WRAP || v == Value.CLAMP || v == Value.MIRRORED_REPEAT) {
+                mWrapS = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
+        }
+
+        public void setWrapT(Value v) {
+            if (v == Value.WRAP || v == Value.CLAMP || v == Value.MIRRORED_REPEAT) {
+                mWrapT = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
+        }
+
+        public void setAnisotropy(float v) {
+            if(v >= 0.0f) {
+                mAniso = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
+        }
+
+        public Sampler create() {
+            mRS.validate();
+            long id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
+                                        mWrapS.mID, mWrapT.mID, mWrapR.mID, mAniso);
+            Sampler sampler = new Sampler(id, mRS);
+            sampler.mMin = mMin;
+            sampler.mMag = mMag;
+            sampler.mWrapS = mWrapS;
+            sampler.mWrapT = mWrapT;
+            sampler.mWrapR = mWrapR;
+            sampler.mAniso = mAniso;
+            return sampler;
+        }
+    }
+
+}
+
diff --git a/android/renderscript/Script.java b/android/renderscript/Script.java
new file mode 100644
index 0000000..f32a2f7
--- /dev/null
+++ b/android/renderscript/Script.java
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.util.SparseArray;
+
+/**
+ * The parent class for all executable scripts. This should not be used by
+ * applications.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Script extends BaseObj {
+
+    /**
+     * KernelID is an identifier for a Script + root function pair. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getKernelID_funcname()".
+     *
+     */
+    public static final class KernelID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        int mSig;
+        KernelID(long id, RenderScript rs, Script s, int slot, int sig) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+            mSig = sig;
+        }
+    }
+
+    private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
+    /**
+     * Only to be used by generated reflected classes.
+     */
+    protected KernelID createKernelID(int slot, int sig, Element ein,
+                                      Element eout) {
+        KernelID k = mKIDs.get(slot);
+        if (k != null) {
+            return k;
+        }
+
+        long id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create KernelID");
+        }
+
+        k = new KernelID(id, mRS, this, slot, sig);
+        mKIDs.put(slot, k);
+        return k;
+    }
+
+    /**
+     * InvokeID is an identifier for an invoke function. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getInvokeID_funcname()".
+     *
+     */
+    public static final class InvokeID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        InvokeID(long id, RenderScript rs, Script s, int slot) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+        }
+    }
+
+    private final SparseArray<InvokeID> mIIDs = new SparseArray<InvokeID>();
+    /**
+     * Only to be used by generated reflected classes.
+     */
+    protected InvokeID createInvokeID(int slot) {
+        InvokeID i = mIIDs.get(slot);
+        if (i != null) {
+            return i;
+        }
+
+        long id = mRS.nScriptInvokeIDCreate(getID(mRS), slot);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create KernelID");
+        }
+
+        i = new InvokeID(id, mRS, this, slot);
+        mIIDs.put(slot, i);
+        return i;
+    }
+
+    /**
+     * FieldID is an identifier for a Script + exported field pair. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getFieldID_funcname()".
+     *
+     */
+    public static final class FieldID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        FieldID(long id, RenderScript rs, Script s, int slot) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+        }
+    }
+
+    private final SparseArray<FieldID> mFIDs = new SparseArray();
+    /**
+     * Only to be used by generated reflected classes.
+     */
+    protected FieldID createFieldID(int slot, Element e) {
+        FieldID f = mFIDs.get(slot);
+        if (f != null) {
+            return f;
+        }
+
+        long id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create FieldID");
+        }
+
+        f = new FieldID(id, mRS, this, slot);
+        mFIDs.put(slot, f);
+        return f;
+    }
+
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    protected void invoke(int slot) {
+        mRS.nScriptInvoke(getID(mRS), slot);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    protected void invoke(int slot, FieldPacker v) {
+        if (v != null) {
+            mRS.nScriptInvokeV(getID(mRS), slot, v.getData());
+        } else {
+            mRS.nScriptInvoke(getID(mRS), slot);
+        }
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    protected void forEach(int slot, Allocation ain, Allocation aout,
+                           FieldPacker v) {
+        forEach(slot, ain, aout, v, null);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    protected void forEach(int slot, Allocation ain, Allocation aout,
+                           FieldPacker v, LaunchOptions sc) {
+        // TODO: Is this necessary if nScriptForEach calls validate as well?
+        mRS.validate();
+        mRS.validateObject(ain);
+        mRS.validateObject(aout);
+
+        if (ain == null && aout == null && sc == null) {
+            throw new RSIllegalArgumentException(
+                "At least one of input allocation, output allocation, or LaunchOptions is required to be non-null.");
+        }
+
+        long[] in_ids = null;
+        if (ain != null) {
+            in_ids    = mInIdsBuffer;
+            in_ids[0] = ain.getID(mRS);
+        }
+
+        long out_id = 0;
+        if (aout != null) {
+            out_id = aout.getID(mRS);
+        }
+
+        byte[] params = null;
+        if (v != null) {
+            params = v.getData();
+        }
+
+        int[] limits = null;
+        if (sc != null) {
+            limits = new int[6];
+
+            limits[0] = sc.xstart;
+            limits[1] = sc.xend;
+            limits[2] = sc.ystart;
+            limits[3] = sc.yend;
+            limits[4] = sc.zstart;
+            limits[5] = sc.zend;
+        }
+
+        mRS.nScriptForEach(getID(mRS), slot, in_ids, out_id, params, limits);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     */
+    protected void forEach(int slot, Allocation[] ains, Allocation aout,
+                           FieldPacker v) {
+
+        // FieldPacker is kept here to support regular params in the future.
+        forEach(slot, ains, aout, v, null);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     */
+    protected void forEach(int slot, Allocation[] ains, Allocation aout,
+                           FieldPacker v, LaunchOptions sc) {
+        // TODO: Is this necessary if nScriptForEach calls validate as well?
+        // FieldPacker is kept here to support regular params in the future.
+        mRS.validate();
+        if (ains != null) {
+            for (Allocation ain : ains) {
+                mRS.validateObject(ain);
+            }
+        }
+        mRS.validateObject(aout);
+
+        if (ains == null && aout == null) {
+            throw new RSIllegalArgumentException(
+                "At least one of ain or aout is required to be non-null.");
+        }
+
+        long[] in_ids;
+        if (ains != null) {
+            in_ids = new long[ains.length];
+            for (int index = 0; index < ains.length; ++index) {
+                in_ids[index] = ains[index].getID(mRS);
+            }
+        } else {
+            in_ids = null;
+        }
+
+        long out_id = 0;
+        if (aout != null) {
+            out_id = aout.getID(mRS);
+        }
+
+        byte[] params = null;
+        if (v != null) {
+            params = v.getData();
+        }
+
+        int[] limits = null;
+        if (sc != null) {
+            limits = new int[6];
+
+            limits[0] = sc.xstart;
+            limits[1] = sc.xend;
+            limits[2] = sc.ystart;
+            limits[3] = sc.yend;
+            limits[4] = sc.zstart;
+            limits[5] = sc.zend;
+        }
+
+        mRS.nScriptForEach(getID(mRS), slot, in_ids, out_id, params, limits);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.  (General reduction)
+     *
+     */
+    protected void reduce(int slot, Allocation[] ains, Allocation aout, LaunchOptions sc) {
+        mRS.validate();
+        if (ains == null || ains.length < 1) {
+            throw new RSIllegalArgumentException(
+                "At least one input is required.");
+        }
+        if (aout == null) {
+            throw new RSIllegalArgumentException(
+                "aout is required to be non-null.");
+        }
+        for (Allocation ain : ains) {
+            mRS.validateObject(ain);
+        }
+
+        long[] in_ids = new long[ains.length];
+        for (int index = 0; index < ains.length; ++index) {
+            in_ids[index] = ains[index].getID(mRS);
+        }
+        long out_id = aout.getID(mRS);
+
+        int[] limits = null;
+        if (sc != null) {
+            limits = new int[6];
+
+            limits[0] = sc.xstart;
+            limits[1] = sc.xend;
+            limits[2] = sc.ystart;
+            limits[3] = sc.yend;
+            limits[4] = sc.zstart;
+            limits[5] = sc.zend;
+        }
+
+        mRS.nScriptReduce(getID(mRS), slot, in_ids, out_id, limits);
+    }
+
+    long[] mInIdsBuffer;
+
+    Script(long id, RenderScript rs) {
+        super(id, rs);
+
+        mInIdsBuffer = new long[1];
+
+        /* The constructors for the derived classes (including ScriptIntrinsic
+         * derived classes and ScriptC derived classes generated by Slang
+         * reflection) seem to be simple enough, so we just put the guard.open()
+         * call here, rather than in the end of the constructor for the derived
+         * class. This, of course, assumes the derived constructor would not
+         * throw any exception after calling this constructor.
+         *
+         * If new derived classes are added with more complicated constructors
+         * that throw exceptions, this call has to be (duplicated and) moved
+         * to the end of each derived class constructor.
+         */
+        guard.open("destroy");
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void bindAllocation(Allocation va, int slot) {
+        mRS.validate();
+        mRS.validateObject(va);
+        if (va != null) {
+
+            android.content.Context context = mRS.getApplicationContext();
+
+            if (context.getApplicationInfo().targetSdkVersion >= 20) {
+                final Type t = va.mType;
+                if (t.hasMipmaps() || t.hasFaces() || (t.getY() != 0) ||
+                    (t.getZ() != 0)) {
+
+                    throw new RSIllegalArgumentException(
+                        "API 20+ only allows simple 1D allocations to be " +
+                        "used with bind.");
+                }
+            }
+            mRS.nScriptBindAllocation(getID(mRS), va.getID(mRS), slot);
+        } else {
+            mRS.nScriptBindAllocation(getID(mRS), 0, slot);
+        }
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, float v) {
+        mRS.nScriptSetVarF(getID(mRS), index, v);
+    }
+    public float getVarF(int index) {
+        return mRS.nScriptGetVarF(getID(mRS), index);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, double v) {
+        mRS.nScriptSetVarD(getID(mRS), index, v);
+    }
+    public double getVarD(int index) {
+        return mRS.nScriptGetVarD(getID(mRS), index);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, int v) {
+        mRS.nScriptSetVarI(getID(mRS), index, v);
+    }
+    public int getVarI(int index) {
+        return mRS.nScriptGetVarI(getID(mRS), index);
+    }
+
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, long v) {
+        mRS.nScriptSetVarJ(getID(mRS), index, v);
+    }
+    public long getVarJ(int index) {
+        return mRS.nScriptGetVarJ(getID(mRS), index);
+    }
+
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, boolean v) {
+        mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0);
+    }
+    public boolean getVarB(int index) {
+        return mRS.nScriptGetVarI(getID(mRS), index) > 0 ? true : false;
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, BaseObj o) {
+        mRS.validate();
+        mRS.validateObject(o);
+        mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS));
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, FieldPacker v) {
+        mRS.nScriptSetVarV(getID(mRS), index, v.getData());
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void setVar(int index, FieldPacker v, Element e, int[] dims) {
+        mRS.nScriptSetVarVE(getID(mRS), index, v.getData(), e.getID(mRS), dims);
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public void getVarV(int index, FieldPacker v) {
+        mRS.nScriptGetVarV(getID(mRS), index, v.getData());
+    }
+
+    public void setTimeZone(String timeZone) {
+        mRS.validate();
+        try {
+            mRS.nScriptSetTimeZone(getID(mRS), timeZone.getBytes("UTF-8"));
+        } catch (java.io.UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public static class Builder {
+        @UnsupportedAppUsage
+        RenderScript mRS;
+
+        @UnsupportedAppUsage
+        Builder(RenderScript rs) {
+            mRS = rs;
+        }
+    }
+
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     */
+    public static class FieldBase {
+        protected Element mElement;
+        protected Allocation mAllocation;
+
+        protected void init(RenderScript rs, int dimx) {
+            mAllocation = Allocation.createSized(rs, mElement, dimx,
+                                                 Allocation.USAGE_SCRIPT);
+        }
+
+        protected void init(RenderScript rs, int dimx, int usages) {
+            mAllocation =
+                Allocation.createSized(rs, mElement, dimx,
+                                       Allocation.USAGE_SCRIPT | usages);
+        }
+
+        protected FieldBase() {
+        }
+
+        public Element getElement() {
+            return mElement;
+        }
+
+        public Type getType() {
+            return mAllocation.getType();
+        }
+
+        public Allocation getAllocation() {
+            return mAllocation;
+        }
+
+        //@Override
+        public void updateAllocation() {
+        }
+    }
+
+
+    /**
+     * Class for specifying the specifics about how a kernel will be
+     * launched.
+     *
+     * This class can specify a potential range of cells on which to
+     * run a kernel.  If no set is called for a dimension then this
+     * class will have no impact on that dimension when the kernel
+     * is executed.
+     *
+     * The forEach kernel launch will operate over the intersection of
+     * the dimensions.
+     *
+     * Example:
+     * LaunchOptions with setX(5, 15)
+     * Allocation with dimension X=10, Y=10
+     * The resulting forEach run would execute over:
+     * x = 5 to 9 (inclusive) and
+     * y = 0 to 9 (inclusive).
+     *
+     *
+     */
+    public static final class LaunchOptions {
+        private int xstart = 0;
+        private int ystart = 0;
+        private int xend = 0;
+        private int yend = 0;
+        private int zstart = 0;
+        private int zend = 0;
+        private int strategy;
+
+        /**
+         * Set the X range. xstartArg is the lowest coordinate of the range,
+         * and xendArg-1 is the highest coordinate of the range.
+         *
+         * @param xstartArg Must be >= 0
+         * @param xendArg Must be > xstartArg
+         *
+         * @return LaunchOptions
+         */
+        public LaunchOptions setX(int xstartArg, int xendArg) {
+            if (xstartArg < 0 || xendArg <= xstartArg) {
+                throw new RSIllegalArgumentException("Invalid dimensions");
+            }
+            xstart = xstartArg;
+            xend = xendArg;
+            return this;
+        }
+
+        /**
+         * Set the Y range. ystartArg is the lowest coordinate of the range,
+         * and yendArg-1 is the highest coordinate of the range.
+         *
+         * @param ystartArg Must be >= 0
+         * @param yendArg Must be > ystartArg
+         *
+         * @return LaunchOptions
+         */
+        public LaunchOptions setY(int ystartArg, int yendArg) {
+            if (ystartArg < 0 || yendArg <= ystartArg) {
+                throw new RSIllegalArgumentException("Invalid dimensions");
+            }
+            ystart = ystartArg;
+            yend = yendArg;
+            return this;
+        }
+
+        /**
+         * Set the Z range. zstartArg is the lowest coordinate of the range,
+         * and zendArg-1 is the highest coordinate of the range.
+         *
+         * @param zstartArg Must be >= 0
+         * @param zendArg Must be > zstartArg
+         *
+         * @return LaunchOptions
+         */
+        public LaunchOptions setZ(int zstartArg, int zendArg) {
+            if (zstartArg < 0 || zendArg <= zstartArg) {
+                throw new RSIllegalArgumentException("Invalid dimensions");
+            }
+            zstart = zstartArg;
+            zend = zendArg;
+            return this;
+        }
+
+
+        /**
+         * Returns the current X start
+         *
+         * @return int current value
+         */
+        public int getXStart() {
+            return xstart;
+        }
+        /**
+         * Returns the current X end
+         *
+         * @return int current value
+         */
+        public int getXEnd() {
+            return xend;
+        }
+        /**
+         * Returns the current Y start
+         *
+         * @return int current value
+         */
+        public int getYStart() {
+            return ystart;
+        }
+        /**
+         * Returns the current Y end
+         *
+         * @return int current value
+         */
+        public int getYEnd() {
+            return yend;
+        }
+        /**
+         * Returns the current Z start
+         *
+         * @return int current value
+         */
+        public int getZStart() {
+            return zstart;
+        }
+        /**
+         * Returns the current Z end
+         *
+         * @return int current value
+         */
+        public int getZEnd() {
+            return zend;
+        }
+
+    }
+}
diff --git a/android/renderscript/ScriptC.java b/android/renderscript/ScriptC.java
new file mode 100644
index 0000000..1866a99
--- /dev/null
+++ b/android/renderscript/ScriptC.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.content.res.Resources;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * The superclass for all user-defined scripts. This is only
+ * intended to be used by the generated derived classes.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class ScriptC extends Script {
+    private static final String TAG = "ScriptC";
+
+    /**
+     * Only intended for use by the generated derived classes.
+     *
+     * @param id
+     * @param rs
+     */
+    protected ScriptC(int id, RenderScript rs) {
+        super(id, rs);
+    }
+    /**
+     * Only intended for use by the generated derived classes.
+     *
+     * @param id
+     * @param rs
+     *
+     */
+    protected ScriptC(long id, RenderScript rs) {
+        super(id, rs);
+    }
+    /**
+     * Only intended for use by the generated derived classes.
+     *
+     *
+     * @param rs
+     * @param resources
+     * @param resourceID
+     */
+    protected ScriptC(RenderScript rs, Resources resources, int resourceID) {
+        super(0, rs);
+        long id = internalCreate(rs, resources, resourceID);
+        if (id == 0) {
+            throw new RSRuntimeException("Loading of ScriptC script failed.");
+        }
+        setID(id);
+    }
+
+    /**
+     * Only intended for use by the generated derived classes.
+     *
+     * @param rs
+     */
+    protected ScriptC(RenderScript rs, String resName, byte[] bitcode32, byte[] bitcode64) {
+        super(0, rs);
+        long id = 0;
+        if (RenderScript.sPointerSize == 4) {
+            id = internalStringCreate(rs, resName, bitcode32);
+        } else {
+            id = internalStringCreate(rs, resName, bitcode64);
+        }
+        if (id == 0) {
+            throw new RSRuntimeException("Loading of ScriptC script failed.");
+        }
+        setID(id);
+    }
+
+    private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
+        byte[] pgm;
+        int pgmLength;
+        InputStream is = resources.openRawResource(resourceID);
+        try {
+            try {
+                pgm = new byte[1024];
+                pgmLength = 0;
+                while(true) {
+                    int bytesLeft = pgm.length - pgmLength;
+                    if (bytesLeft == 0) {
+                        byte[] buf2 = new byte[pgm.length * 2];
+                        System.arraycopy(pgm, 0, buf2, 0, pgm.length);
+                        pgm = buf2;
+                        bytesLeft = pgm.length - pgmLength;
+                    }
+                    int bytesRead = is.read(pgm, pgmLength, bytesLeft);
+                    if (bytesRead <= 0) {
+                        break;
+                    }
+                    pgmLength += bytesRead;
+                }
+            } finally {
+                is.close();
+            }
+        } catch(IOException e) {
+            throw new Resources.NotFoundException();
+        }
+
+        String resName = resources.getResourceEntryName(resourceID);
+
+        //        Log.v(TAG, "Create script for resource = " + resName);
+        return rs.nScriptCCreate(resName, RenderScript.getCachePath(), pgm, pgmLength);
+    }
+
+    private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) {
+        //        Log.v(TAG, "Create script for resource = " + resName);
+        return rs.nScriptCCreate(resName, RenderScript.getCachePath(), bitcode, bitcode.length);
+    }
+}
diff --git a/android/renderscript/ScriptGroup.java b/android/renderscript/ScriptGroup.java
new file mode 100644
index 0000000..5cdb9cf
--- /dev/null
+++ b/android/renderscript/ScriptGroup.java
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.util.Log;
+import android.util.Pair;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A group of kernels that are executed
+ * together with one execution call as if they were a single kernel
+ * <p>
+ * In addition to kernels, a script group may contain invocable functions as well.
+ * A script group may take inputs and generate outputs, which are consumed and
+ * produced by its member kernels.
+ * Inside a script group, outputs from one kernel can be passed to another kernel as inputs.
+ * The API disallows cyclic dependencies among kernels in a script group,
+ * effectively making it a directed acyclic graph (DAG) of kernels.
+ * <p>
+ * Grouping kernels together allows for more efficient execution. For example,
+ * runtime and compiler optimization can be applied to reduce computation and
+ * communication overhead, and to make better use of the CPU and the GPU.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptGroup extends BaseObj {
+    private static final String TAG = "ScriptGroup";
+    IO mOutputs[];
+    IO mInputs[];
+
+    static class IO {
+        Script.KernelID mKID;
+        Allocation mAllocation;
+
+        IO(Script.KernelID s) {
+            mKID = s;
+        }
+    }
+
+    static class ConnectLine {
+        ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
+            mFrom = from;
+            mToK = to;
+            mAllocationType = t;
+        }
+
+        ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
+            mFrom = from;
+            mToF = to;
+            mAllocationType = t;
+        }
+
+        Script.FieldID mToF;
+        Script.KernelID mToK;
+        Script.KernelID mFrom;
+        Type mAllocationType;
+    }
+
+    static class Node {
+        Script mScript;
+        ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
+        ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
+        ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
+        int dagNumber;
+
+        Node mNext;
+
+        Node(Script s) {
+            mScript = s;
+        }
+    }
+
+
+    /**
+     * An opaque class for closures
+     * <p>
+     * A closure represents a function call to a kernel or invocable function,
+     * combined with arguments and values for global variables. A closure is
+     * created using the {@link android.renderscript.ScriptGroup.Builder2#addKernel} or
+     * {@link android.renderscript.ScriptGroup.Builder2#addInvoke}
+     * method.
+     */
+
+    public static final class Closure extends BaseObj {
+        private Object[] mArgs;
+        private Allocation mReturnValue;
+        private Map<Script.FieldID, Object> mBindings;
+
+        private Future mReturnFuture;
+        private Map<Script.FieldID, Future> mGlobalFuture;
+
+        private FieldPacker mFP;
+
+        private static final String TAG = "Closure";
+
+        Closure(long id, RenderScript rs) {
+            super(id, rs);
+        }
+
+        Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
+                       Object[] args, Map<Script.FieldID, Object> globals) {
+            super(0, rs);
+
+            mArgs = args;
+            mReturnValue = Allocation.createTyped(rs, returnType);
+            mBindings = globals;
+            mGlobalFuture = new HashMap<Script.FieldID, Future>();
+
+            int numValues = args.length + globals.size();
+
+            long[] fieldIDs = new long[numValues];
+            long[] values = new long[numValues];
+            int[] sizes = new int[numValues];
+            long[] depClosures = new long[numValues];
+            long[] depFieldIDs = new long[numValues];
+
+            int i;
+            for (i = 0; i < args.length; i++) {
+                fieldIDs[i] = 0;
+                retrieveValueAndDependenceInfo(rs, i, null, args[i],
+                                               values, sizes, depClosures, depFieldIDs);
+            }
+            for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
+                Object obj = entry.getValue();
+                Script.FieldID fieldID = entry.getKey();
+                fieldIDs[i] = fieldID.getID(rs);
+                retrieveValueAndDependenceInfo(rs, i, fieldID, obj,
+                                               values, sizes, depClosures, depFieldIDs);
+                i++;
+            }
+
+            long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
+                                        fieldIDs, values, sizes, depClosures, depFieldIDs);
+
+            setID(id);
+
+            guard.open("destroy");
+        }
+
+        Closure(RenderScript rs, Script.InvokeID invokeID,
+                       Object[] args, Map<Script.FieldID, Object> globals) {
+            super(0, rs);
+            mFP = FieldPacker.createFromArray(args);
+
+            mArgs = args;
+            mBindings = globals;
+            mGlobalFuture = new HashMap<Script.FieldID, Future>();
+
+            int numValues = globals.size();
+
+            long[] fieldIDs = new long[numValues];
+            long[] values = new long[numValues];
+            int[] sizes = new int[numValues];
+            long[] depClosures = new long[numValues];
+            long[] depFieldIDs = new long[numValues];
+
+            int i = 0;
+            for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
+                Object obj = entry.getValue();
+                Script.FieldID fieldID = entry.getKey();
+                fieldIDs[i] = fieldID.getID(rs);
+                retrieveValueAndDependenceInfo(rs, i, fieldID, obj, values,
+                                               sizes, depClosures, depFieldIDs);
+                i++;
+            }
+
+            long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
+                                              values, sizes);
+
+            setID(id);
+
+            guard.open("destroy");
+        }
+
+        /**
+         * Destroys this Closure and the Allocation for its return value
+         */
+        public void destroy() {
+            super.destroy();
+            if (mReturnValue != null) {
+                mReturnValue.destroy();
+            }
+        }
+
+        protected void finalize() throws Throwable {
+            // Set null mReturnValue to avoid double-destroying it, in case its
+            // finalizer races ahead.
+            mReturnValue = null;
+            super.finalize();
+        }
+
+        private void retrieveValueAndDependenceInfo(RenderScript rs,
+                                                    int index, Script.FieldID fid, Object obj,
+                                                    long[] values, int[] sizes,
+                                                    long[] depClosures,
+                                                    long[] depFieldIDs) {
+
+            if (obj instanceof Future) {
+                Future f = (Future)obj;
+                obj = f.getValue();
+                depClosures[index] = f.getClosure().getID(rs);
+                Script.FieldID fieldID = f.getFieldID();
+                depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
+            } else {
+                depClosures[index] = 0;
+                depFieldIDs[index] = 0;
+            }
+
+            if (obj instanceof Input) {
+                Input unbound = (Input)obj;
+                if (index < mArgs.length) {
+                    unbound.addReference(this, index);
+                } else {
+                    unbound.addReference(this, fid);
+                }
+                values[index] = 0;
+                sizes[index] = 0;
+            } else {
+                ValueAndSize vs = new ValueAndSize(rs, obj);
+                values[index] = vs.value;
+                sizes[index] = vs.size;
+            }
+        }
+
+        /**
+         * Returns the future for the return value
+         *
+         * @return a future
+         */
+
+        public Future getReturn() {
+            if (mReturnFuture == null) {
+                mReturnFuture = new Future(this, null, mReturnValue);
+            }
+
+            return mReturnFuture;
+        }
+
+        /**
+         * Returns the future for a global variable
+         *
+         * @param field the field ID for the global variable
+         * @return a future
+         */
+
+        public Future getGlobal(Script.FieldID field) {
+            Future f = mGlobalFuture.get(field);
+
+            if (f == null) {
+                // If the field is not bound to this closure, this will return a future
+                // without an associated value (reference). So this is not working for
+                // cross-module (cross-script) linking in this case where a field not
+                // explicitly bound.
+                Object obj = mBindings.get(field);
+                if (obj instanceof Future) {
+                    obj = ((Future)obj).getValue();
+                }
+                f = new Future(this, field, obj);
+                mGlobalFuture.put(field, f);
+            }
+
+            return f;
+        }
+
+        void setArg(int index, Object obj) {
+            if (obj instanceof Future) {
+                obj = ((Future)obj).getValue();
+            }
+            mArgs[index] = obj;
+            ValueAndSize vs = new ValueAndSize(mRS, obj);
+            mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
+        }
+
+        void setGlobal(Script.FieldID fieldID, Object obj) {
+            if (obj instanceof Future) {
+                obj = ((Future)obj).getValue();
+            }
+            mBindings.put(fieldID, obj);
+            ValueAndSize vs = new ValueAndSize(mRS, obj);
+            mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
+        }
+
+        private static final class ValueAndSize {
+            public ValueAndSize(RenderScript rs, Object obj) {
+                if (obj instanceof Allocation) {
+                    value = ((Allocation)obj).getID(rs);
+                    // Special value for size to tell the runtime and driver that
+                    // the value is an Allocation
+                    size = -1;
+                } else if (obj instanceof Boolean) {
+                    value = ((Boolean)obj).booleanValue() ? 1 : 0;
+                    size = 4;
+                } else if (obj instanceof Integer) {
+                    value = ((Integer)obj).longValue();
+                    size = 4;
+                } else if (obj instanceof Long) {
+                    value = ((Long)obj).longValue();
+                    size = 8;
+                } else if (obj instanceof Float) {
+                    value = Float.floatToRawIntBits(((Float)obj).floatValue());
+                    size = 4;
+                } else if (obj instanceof Double) {
+                    value = Double.doubleToRawLongBits(((Double)obj).doubleValue());
+                    size = 8;
+                }
+            }
+            public long value;
+            public int size;
+        }
+    }
+
+    /**
+     * An opaque class for futures
+     * <p>
+     * A future represents an output of a closure, either the return value of
+     * the function, or the value of a global variable written by the function.
+     * A future is created by calling the {@link Closure#getReturn}  or
+     * {@link Closure#getGlobal} method.
+     */
+
+    public static final class Future {
+        Closure mClosure;
+        Script.FieldID mFieldID;
+        Object mValue;
+
+        Future(Closure closure, Script.FieldID fieldID, Object value) {
+            mClosure = closure;
+            mFieldID = fieldID;
+            mValue = value;
+        }
+
+        Closure getClosure() { return mClosure; }
+        Script.FieldID getFieldID() { return mFieldID; }
+        Object getValue() { return mValue; }
+    }
+
+    /**
+     * An opaque class for script group inputs
+     * <p>
+     * Created by calling the {@link Builder2#addInput} method. The value
+     * is assigned in {@link ScriptGroup#execute(Object...)} method as
+     * one of its arguments. Arguments to the execute method should be in
+     * the same order as intputs are added using the addInput method.
+     */
+
+    public static final class Input {
+        // Either mFieldID or mArgIndex should be set but not both.
+        List<Pair<Closure, Script.FieldID>> mFieldID;
+        // -1 means unset. Legal values are 0 .. n-1, where n is the number of
+        // arguments for the referencing closure.
+        List<Pair<Closure, Integer>> mArgIndex;
+        Object mValue;
+
+        Input() {
+            mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
+            mArgIndex = new ArrayList<Pair<Closure, Integer>>();
+        }
+
+        void addReference(Closure closure, int index) {
+            mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
+        }
+
+        void addReference(Closure closure, Script.FieldID fieldID) {
+            mFieldID.add(Pair.create(closure, fieldID));
+        }
+
+        void set(Object value) {
+            mValue = value;
+            for (Pair<Closure, Integer> p : mArgIndex) {
+                Closure closure = p.first;
+                int index = p.second.intValue();
+                closure.setArg(index, value);
+            }
+            for (Pair<Closure, Script.FieldID> p : mFieldID) {
+                Closure closure = p.first;
+                Script.FieldID fieldID = p.second;
+                closure.setGlobal(fieldID, value);
+            }
+        }
+
+        Object get() { return mValue; }
+    }
+
+    private String mName;
+    private List<Closure> mClosures;
+    private List<Input> mInputs2;
+    private Future[] mOutputs2;
+
+    ScriptGroup(long id, RenderScript rs) {
+        super(id, rs);
+        guard.open("destroy");
+    }
+
+    ScriptGroup(RenderScript rs, String name, List<Closure> closures,
+                 List<Input> inputs, Future[] outputs) {
+        super(0, rs);
+        mName = name;
+        mClosures = closures;
+        mInputs2 = inputs;
+        mOutputs2 = outputs;
+
+        long[] closureIDs = new long[closures.size()];
+        for (int i = 0; i < closureIDs.length; i++) {
+            closureIDs[i] = closures.get(i).getID(rs);
+        }
+        long id = rs.nScriptGroup2Create(name, RenderScript.getCachePath(), closureIDs);
+        setID(id);
+        guard.open("destroy");
+    }
+
+    /**
+     * Executes a script group
+     *
+     * @param inputs Values for inputs to the script group, in the order as the
+     *        inputs are added via {@link Builder2#addInput}.
+     * @return Outputs of the script group as an array of objects, in the order
+     *         as futures are passed to {@link Builder2#create}.
+     */
+
+    public Object[] execute(Object... inputs) {
+        if (inputs.length < mInputs2.size()) {
+            Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
+                  "less than expected " + mInputs2.size());
+            return null;
+        }
+
+        if (inputs.length > mInputs2.size()) {
+            Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
+                  "more than expected " + mInputs2.size());
+        }
+
+        for (int i = 0; i < mInputs2.size(); i++) {
+            Object obj = inputs[i];
+            if (obj instanceof Future || obj instanceof Input) {
+                Log.e(TAG, this.toString() + ": input " + i +
+                      " is a future or unbound value");
+                return null;
+            }
+            Input unbound = mInputs2.get(i);
+            unbound.set(obj);
+        }
+
+        mRS.nScriptGroup2Execute(getID(mRS));
+
+        Object[] outputObjs = new Object[mOutputs2.length];
+        int i = 0;
+        for (Future f : mOutputs2) {
+            Object output = f.getValue();
+            if (output instanceof Input) {
+                output = ((Input)output).get();
+            }
+            outputObjs[i++] = output;
+        }
+        return outputObjs;
+    }
+
+    /**
+     * Sets an input of the ScriptGroup. This specifies an
+     * Allocation to be used for kernels that require an input
+     * Allocation provided from outside of the ScriptGroup.
+     *
+     * @deprecated Set arguments to {@link #execute(Object...)} instead.
+     *
+     * @param s The ID of the kernel where the allocation should be
+     *          connected.
+     * @param a The allocation to connect.
+     */
+    public void setInput(Script.KernelID s, Allocation a) {
+        for (int ct=0; ct < mInputs.length; ct++) {
+            if (mInputs[ct].mKID == s) {
+                mInputs[ct].mAllocation = a;
+                mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
+                return;
+            }
+        }
+        throw new RSIllegalArgumentException("Script not found");
+    }
+
+    /**
+     * Sets an output of the ScriptGroup. This specifies an
+     * Allocation to be used for the kernels that require an output
+     * Allocation visible after the ScriptGroup is executed.
+     *
+     * @deprecated Use return value of {@link #execute(Object...)} instead.
+     *
+     * @param s The ID of the kernel where the allocation should be
+     *          connected.
+     * @param a The allocation to connect.
+     */
+    public void setOutput(Script.KernelID s, Allocation a) {
+        for (int ct=0; ct < mOutputs.length; ct++) {
+            if (mOutputs[ct].mKID == s) {
+                mOutputs[ct].mAllocation = a;
+                mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
+                return;
+            }
+        }
+        throw new RSIllegalArgumentException("Script not found");
+    }
+
+    /**
+     * Execute the ScriptGroup.  This will run all the kernels in
+     * the ScriptGroup.  No internal connection results will be visible
+     * after execution of the ScriptGroup.
+     *
+     * @deprecated Use {@link #execute} instead.
+     *
+     */
+    public void execute() {
+        mRS.nScriptGroupExecute(getID(mRS));
+    }
+
+
+    /**
+     * Helper class to build a ScriptGroup. A ScriptGroup is
+     * created in two steps.
+     * <p>
+     * First, all kernels to be used by the ScriptGroup should be added.
+     * <p>
+     * Second, add connections between kernels. There are two types
+     * of connections: kernel to kernel and kernel to field.
+     * Kernel to kernel allows a kernel's output to be passed to
+     * another kernel as input. Kernel to field allows the output of
+     * one kernel to be bound as a script global. Kernel to kernel is
+     * higher performance and should be used where possible.
+     * <p>
+     * A ScriptGroup must contain a single directed acyclic graph (DAG); it
+     * cannot contain cycles. Currently, all kernels used in a ScriptGroup
+     * must come from different Script objects. Additionally, all kernels
+     * in a ScriptGroup must have at least one input, output, or internal
+     * connection.
+     * <p>
+     * Once all connections are made, a call to {@link #create} will
+     * return the ScriptGroup object.
+     *
+     * @deprecated Use {@link Builder2} instead.
+     *
+     */
+    public static final class Builder {
+        private RenderScript mRS;
+        private ArrayList<Node> mNodes = new ArrayList<Node>();
+        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
+        private int mKernelCount;
+
+        /**
+         * Create a Builder for generating a ScriptGroup.
+         *
+         *
+         * @param rs The RenderScript context.
+         */
+        public Builder(RenderScript rs) {
+            mRS = rs;
+        }
+
+        // do a DFS from original node, looking for original node
+        // any cycle that could be created must contain original node
+        private void validateCycle(Node target, Node original) {
+            for (int ct = 0; ct < target.mOutputs.size(); ct++) {
+                final ConnectLine cl = target.mOutputs.get(ct);
+                if (cl.mToK != null) {
+                    Node tn = findNode(cl.mToK.mScript);
+                    if (tn.equals(original)) {
+                        throw new RSInvalidStateException("Loops in group not allowed.");
+                    }
+                    validateCycle(tn, original);
+                }
+                if (cl.mToF != null) {
+                    Node tn = findNode(cl.mToF.mScript);
+                    if (tn.equals(original)) {
+                        throw new RSInvalidStateException("Loops in group not allowed.");
+                    }
+                    validateCycle(tn, original);
+                }
+            }
+        }
+
+        private void mergeDAGs(int valueUsed, int valueKilled) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (mNodes.get(ct).dagNumber == valueKilled)
+                    mNodes.get(ct).dagNumber = valueUsed;
+            }
+        }
+
+        private void validateDAGRecurse(Node n, int dagNumber) {
+            // combine DAGs if this node has been seen already
+            if (n.dagNumber != 0 && n.dagNumber != dagNumber) {
+                mergeDAGs(n.dagNumber, dagNumber);
+                return;
+            }
+
+            n.dagNumber = dagNumber;
+            for (int ct=0; ct < n.mOutputs.size(); ct++) {
+                final ConnectLine cl = n.mOutputs.get(ct);
+                if (cl.mToK != null) {
+                    Node tn = findNode(cl.mToK.mScript);
+                    validateDAGRecurse(tn, dagNumber);
+                }
+                if (cl.mToF != null) {
+                    Node tn = findNode(cl.mToF.mScript);
+                    validateDAGRecurse(tn, dagNumber);
+                }
+            }
+        }
+
+        private void validateDAG() {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                if (n.mInputs.size() == 0) {
+                    if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
+                        String msg = "Groups cannot contain unconnected scripts";
+                        throw new RSInvalidStateException(msg);
+                    }
+                    validateDAGRecurse(n, ct+1);
+                }
+            }
+            int dagNumber = mNodes.get(0).dagNumber;
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (mNodes.get(ct).dagNumber != dagNumber) {
+                    throw new RSInvalidStateException("Multiple DAGs in group not allowed.");
+                }
+            }
+        }
+
+        private Node findNode(Script s) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (s == mNodes.get(ct).mScript) {
+                    return mNodes.get(ct);
+                }
+            }
+            return null;
+        }
+
+        private Node findNode(Script.KernelID k) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+                    if (k == n.mKernels.get(ct2)) {
+                        return n;
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Adds a Kernel to the group.
+         *
+         *
+         * @param k The kernel to add.
+         *
+         * @return Builder Returns this.
+         */
+        public Builder addKernel(Script.KernelID k) {
+            if (mLines.size() != 0) {
+                throw new RSInvalidStateException(
+                    "Kernels may not be added once connections exist.");
+            }
+
+            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
+            if (findNode(k) != null) {
+                return this;
+            }
+            //android.util.Log.v("RSR", "addKernel 2 ");
+            mKernelCount++;
+            Node n = findNode(k.mScript);
+            if (n == null) {
+                //android.util.Log.v("RSR", "addKernel 3 ");
+                n = new Node(k.mScript);
+                mNodes.add(n);
+            }
+            n.mKernels.add(k);
+            return this;
+        }
+
+        /**
+         * Adds a connection to the group.
+         *
+         *
+         * @param t The type of the connection. This is used to
+         *          determine the kernel launch sizes on the source side
+         *          of this connection.
+         * @param from The source for the connection.
+         * @param to The destination of the connection.
+         *
+         * @return Builder Returns this
+         */
+        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
+            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+            Node nf = findNode(from);
+            if (nf == null) {
+                throw new RSInvalidStateException("From script not found.");
+            }
+
+            Node nt = findNode(to.mScript);
+            if (nt == null) {
+                throw new RSInvalidStateException("To script not found.");
+            }
+
+            ConnectLine cl = new ConnectLine(t, from, to);
+            mLines.add(new ConnectLine(t, from, to));
+
+            nf.mOutputs.add(cl);
+            nt.mInputs.add(cl);
+
+            validateCycle(nf, nf);
+            return this;
+        }
+
+        /**
+         * Adds a connection to the group.
+         *
+         *
+         * @param t The type of the connection. This is used to
+         *          determine the kernel launch sizes for both sides of
+         *          this connection.
+         * @param from The source for the connection.
+         * @param to The destination of the connection.
+         *
+         * @return Builder Returns this
+         */
+        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
+            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+            Node nf = findNode(from);
+            if (nf == null) {
+                throw new RSInvalidStateException("From script not found.");
+            }
+
+            Node nt = findNode(to);
+            if (nt == null) {
+                throw new RSInvalidStateException("To script not found.");
+            }
+
+            ConnectLine cl = new ConnectLine(t, from, to);
+            mLines.add(new ConnectLine(t, from, to));
+
+            nf.mOutputs.add(cl);
+            nt.mInputs.add(cl);
+
+            validateCycle(nf, nf);
+            return this;
+        }
+
+
+
+        /**
+         * Creates the Script group.
+         *
+         *
+         * @return ScriptGroup The new ScriptGroup
+         */
+        public ScriptGroup create() {
+
+            if (mNodes.size() == 0) {
+                throw new RSInvalidStateException("Empty script groups are not allowed");
+            }
+
+            // reset DAG numbers in case we're building a second group
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                mNodes.get(ct).dagNumber = 0;
+            }
+            validateDAG();
+
+            ArrayList<IO> inputs = new ArrayList<IO>();
+            ArrayList<IO> outputs = new ArrayList<IO>();
+
+            long[] kernels = new long[mKernelCount];
+            int idx = 0;
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+                    final Script.KernelID kid = n.mKernels.get(ct2);
+                    kernels[idx++] = kid.getID(mRS);
+
+                    boolean hasInput = false;
+                    boolean hasOutput = false;
+                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
+                        if (n.mInputs.get(ct3).mToK == kid) {
+                            hasInput = true;
+                        }
+                    }
+                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
+                        if (n.mOutputs.get(ct3).mFrom == kid) {
+                            hasOutput = true;
+                        }
+                    }
+                    if (!hasInput) {
+                        inputs.add(new IO(kid));
+                    }
+                    if (!hasOutput) {
+                        outputs.add(new IO(kid));
+                    }
+
+                }
+            }
+            if (idx != mKernelCount) {
+                throw new RSRuntimeException("Count mismatch, should not happen.");
+            }
+
+            long[] src = new long[mLines.size()];
+            long[] dstk = new long[mLines.size()];
+            long[] dstf = new long[mLines.size()];
+            long[] types = new long[mLines.size()];
+
+            for (int ct=0; ct < mLines.size(); ct++) {
+                ConnectLine cl = mLines.get(ct);
+                src[ct] = cl.mFrom.getID(mRS);
+                if (cl.mToK != null) {
+                    dstk[ct] = cl.mToK.getID(mRS);
+                }
+                if (cl.mToF != null) {
+                    dstf[ct] = cl.mToF.getID(mRS);
+                }
+                types[ct] = cl.mAllocationType.getID(mRS);
+            }
+
+            long id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
+            if (id == 0) {
+                throw new RSRuntimeException("Object creation error, should not happen.");
+            }
+
+            ScriptGroup sg = new ScriptGroup(id, mRS);
+            sg.mOutputs = new IO[outputs.size()];
+            for (int ct=0; ct < outputs.size(); ct++) {
+                sg.mOutputs[ct] = outputs.get(ct);
+            }
+
+            sg.mInputs = new IO[inputs.size()];
+            for (int ct=0; ct < inputs.size(); ct++) {
+                sg.mInputs[ct] = inputs.get(ct);
+            }
+
+            return sg;
+        }
+
+    }
+
+    /**
+     * Represents a binding of a value to a global variable in a
+     * kernel or invocable function. Used in closure creation.
+     */
+
+    public static final class Binding {
+        private final Script.FieldID mField;
+        private final Object mValue;
+
+        /**
+         * Returns a Binding object that binds value to field
+         *
+         * @param field the Script.FieldID of the global variable
+         * @param value the value
+         */
+
+        public Binding(Script.FieldID field, Object value) {
+            mField = field;
+            mValue = value;
+        }
+
+        /**
+         * Returns the field ID
+         */
+
+        Script.FieldID getField() { return mField; }
+
+        /**
+         * Returns the value
+         */
+
+        Object getValue() { return mValue; }
+    }
+
+    /**
+     * The builder class for creating script groups
+     * <p>
+     * A script group is created using closures (see class {@link Closure}).
+     * A closure is a function call to a kernel or
+     * invocable function. Each function argument or global variable accessed inside
+     * the function is bound to 1) a known value, 2) a script group input
+     * (see class {@link Input}), or 3) a
+     * future (see class {@link Future}).
+     * A future is the output of a closure, either the return value of the
+     * function or a global variable written by that function.
+     * <p>
+     * Closures are created using the {@link #addKernel} or {@link #addInvoke}
+     * methods.
+     * When a closure is created, futures from previously created closures
+     * can be used as its inputs.
+     * External script group inputs can be used as inputs to individual closures as well.
+     * An external script group input is created using the {@link #addInput} method.
+     * A script group is created by a call to the {@link #create} method, which
+     * accepts an array of futures as the outputs for the script group.
+     * <p>
+     * Closures in a script group can be evaluated in any order as long as the
+     * following conditions are met:
+     * 1) a closure must be evaluated before any other closures that take its
+     * futures as inputs;
+     * 2) all closures added before an invoke closure must be evaluated
+     * before it;
+     * and 3) all closures added after an invoke closure must be evaluated after
+     * it.
+     * As a special case, the order that the closures are added is a legal
+     * evaluation order. However, other evaluation orders are possible, including
+     * concurrently evaluating independent closures.
+     */
+
+    public static final class Builder2 {
+        RenderScript mRS;
+        List<Closure> mClosures;
+        List<Input> mInputs;
+        private static final String TAG = "ScriptGroup.Builder2";
+
+        /**
+         * Returns a Builder object
+         *
+         * @param rs the RenderScript context
+         */
+        public Builder2(RenderScript rs) {
+            mRS = rs;
+            mClosures = new ArrayList<Closure>();
+            mInputs = new ArrayList<Input>();
+        }
+
+        /**
+         * Adds a closure for a kernel
+         *
+         * @param k Kernel ID for the kernel function
+         * @param returnType Allocation type for the return value
+         * @param args arguments to the kernel function
+         * @param globalBindings bindings for global variables
+         * @return a closure
+         */
+
+        private Closure addKernelInternal(Script.KernelID k, Type returnType, Object[] args,
+                                          Map<Script.FieldID, Object> globalBindings) {
+            Closure c = new Closure(mRS, k, returnType, args, globalBindings);
+            mClosures.add(c);
+            return c;
+        }
+
+        /**
+         * Adds a closure for an invocable function
+         *
+         * @param invoke Invoke ID for the invocable function
+         * @param args arguments to the invocable function
+         * @param globalBindings bindings for global variables
+         * @return a closure
+         */
+
+        private Closure addInvokeInternal(Script.InvokeID invoke, Object[] args,
+                                          Map<Script.FieldID, Object> globalBindings) {
+            Closure c = new Closure(mRS, invoke, args, globalBindings);
+            mClosures.add(c);
+            return c;
+        }
+
+        /**
+         * Adds a script group input
+         *
+         * @return a script group input, which can be used as an argument or a value to
+         *     a global variable for creating closures
+         */
+        public Input addInput() {
+            Input unbound = new Input();
+            mInputs.add(unbound);
+            return unbound;
+        }
+
+        /**
+         * Adds a closure for a kernel
+         *
+         * @param k Kernel ID for the kernel function
+         * @param argsAndBindings arguments followed by bindings for global variables
+         * @return a closure
+         */
+
+        public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
+            ArrayList<Object> args = new ArrayList<Object>();
+            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
+            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
+                return null;
+            }
+            return addKernelInternal(k, returnType, args.toArray(), bindingMap);
+        }
+
+        /**
+         * Adds a closure for an invocable function
+         *
+         * @param invoke Invoke ID for the invocable function
+         * @param argsAndBindings arguments followed by bindings for global variables
+         * @return a closure
+         */
+
+        public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
+            ArrayList<Object> args = new ArrayList<Object>();
+            Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
+            if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) {
+                return null;
+            }
+            return addInvokeInternal(invoke, args.toArray(), bindingMap);
+        }
+
+        /**
+         * Creates a script group
+         *
+         * @param name name for the script group. Legal names can only contain letters, digits,
+         *        '-', or '_'. The name can be no longer than 100 characters.
+         *        Try to use unique names, to avoid name conflicts and reduce
+         *        the cost of group creation.
+         * @param outputs futures intended as outputs of the script group
+         * @return a script group
+         */
+
+        public ScriptGroup create(String name, Future... outputs) {
+            if (name == null || name.isEmpty() || name.length() > 100 ||
+                !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) {
+                throw new RSIllegalArgumentException("invalid script group name");
+            }
+            ScriptGroup ret = new ScriptGroup(mRS, name, mClosures, mInputs, outputs);
+            mClosures = new ArrayList<Closure>();
+            mInputs = new ArrayList<Input>();
+            return ret;
+        }
+
+        private boolean seperateArgsAndBindings(Object[] argsAndBindings,
+                                                ArrayList<Object> args,
+                                                Map<Script.FieldID, Object> bindingMap) {
+            int i;
+            for (i = 0; i < argsAndBindings.length; i++) {
+                if (argsAndBindings[i] instanceof Binding) {
+                    break;
+                }
+                args.add(argsAndBindings[i]);
+            }
+
+            for (; i < argsAndBindings.length; i++) {
+                if (!(argsAndBindings[i] instanceof Binding)) {
+                    return false;
+                }
+                Binding b = (Binding)argsAndBindings[i];
+                bindingMap.put(b.getField(), b.getValue());
+            }
+
+            return true;
+        }
+
+    }
+
+    /**
+     * Destroy this ScriptGroup and all Closures in it
+     */
+    public void destroy() {
+        super.destroy();
+        // ScriptGroup created using the old Builder class does not
+        // initialize the field mClosures
+        if (mClosures != null) {
+            for (Closure c : mClosures) {
+                c.destroy();
+            }
+        }
+    }
+}
diff --git a/android/renderscript/ScriptIntrinsic.java b/android/renderscript/ScriptIntrinsic.java
new file mode 100644
index 0000000..8d65422
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsic.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Base class for all Intrinsic scripts. An intrinsic is a script
+ * that implements a pre-defined function. Intrinsics are
+ * provided to provide efficient implementations of common
+ * operations.
+ *
+ * Not intended for direct use.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+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/android/renderscript/ScriptIntrinsic3DLUT.java b/android/renderscript/ScriptIntrinsic3DLUT.java
new file mode 100644
index 0000000..7a2847e
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsic3DLUT.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ *
+ * Intrinsic for converting RGB to RGBA by using a 3D lookup table.  The
+ * incoming r,g,b values are use as normalized x,y,z coordinates into a 3D
+ * allocation.  The 8 nearest values are sampled and linearly interpolated.  The
+ * result is placed in the output.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsic3DLUT extends ScriptIntrinsic {
+    private Allocation mLUT;
+    private Element mElement;
+
+    private ScriptIntrinsic3DLUT(long id, RenderScript rs, Element e) {
+        super(id, rs);
+        mElement = e;
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * The defaults tables are identity.
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsic3DLUT
+     */
+    public static ScriptIntrinsic3DLUT create(RenderScript rs, Element e) {
+        long id = rs.nScriptIntrinsicCreate(8, e.getID(rs));
+
+        if (!e.isCompatible(Element.U8_4(rs))) {
+            throw new RSIllegalArgumentException("Element must be compatible with uchar4.");
+        }
+
+        return new ScriptIntrinsic3DLUT(id, rs, e);
+    }
+
+    /**
+     * Sets the {@link android.renderscript.Allocation} to be used as the lookup table.
+     *
+     * The lookup table must use the same {@link android.renderscript.Element} as the intrinsic.
+     *
+     */
+
+    public void setLUT(Allocation lut) {
+        final Type t = lut.getType();
+
+        if (t.getZ() == 0) {
+            throw new RSIllegalArgumentException("LUT must be 3d.");
+        }
+
+        if (!t.getElement().isCompatible(mElement)) {
+            throw new RSIllegalArgumentException("LUT element type must match.");
+        }
+
+        mLUT = lut;
+        setVar(0, mLUT);
+    }
+
+
+    /**
+     * Invoke the kernel and apply the lookup to each cell of ain
+     * and copy to aout.
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     */
+    public void forEach(Allocation ain, Allocation aout) {
+        forEach(ain, aout, null);
+    }
+
+    /**
+     * Invoke the kernel and apply the lookup to each cell of ain
+     * and copy to aout.
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     * @param opt Launch options for kernel
+     */
+    public void forEach(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        forEach(0, ain, aout, null, opt);
+    }
+
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
+}
+
diff --git a/android/renderscript/ScriptIntrinsicBLAS.java b/android/renderscript/ScriptIntrinsicBLAS.java
new file mode 100644
index 0000000..16cc799
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicBLAS.java
@@ -0,0 +1,3312 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.annotation.IntDef;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ *
+ * ScriptIntrinsicBLAS class provides high performance RenderScript APIs to BLAS.
+ *
+ * The BLAS (Basic Linear Algebra Subprograms) are routines that provide standard
+ * building blocks for performing basic vector and matrix operations.
+ *
+ * For detailed description of BLAS, please refer to http://www.netlib.org/blas/
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicBLAS extends ScriptIntrinsic {
+    private Allocation mLUT;
+
+    private ScriptIntrinsicBLAS(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    private static final int RsBlas_sdsdot = 1;
+    private static final int RsBlas_dsdot = 2;
+    private static final int RsBlas_sdot = 3;
+    private static final int RsBlas_ddot = 4;
+    private static final int RsBlas_cdotu_sub = 5;
+    private static final int RsBlas_cdotc_sub = 6;
+    private static final int RsBlas_zdotu_sub = 7;
+    private static final int RsBlas_zdotc_sub = 8;
+    private static final int RsBlas_snrm2 = 9;
+    private static final int RsBlas_sasum = 10;
+    private static final int RsBlas_dnrm2 = 11;
+    private static final int RsBlas_dasum = 12;
+    private static final int RsBlas_scnrm2 = 13;
+    private static final int RsBlas_scasum = 14;
+    private static final int RsBlas_dznrm2 = 15;
+    private static final int RsBlas_dzasum = 16;
+    private static final int RsBlas_isamax = 17;
+    private static final int RsBlas_idamax = 18;
+    private static final int RsBlas_icamax = 19;
+    private static final int RsBlas_izamax = 20;
+    private static final int RsBlas_sswap = 21;
+    private static final int RsBlas_scopy = 22;
+    private static final int RsBlas_saxpy = 23;
+    private static final int RsBlas_dswap = 24;
+    private static final int RsBlas_dcopy = 25;
+    private static final int RsBlas_daxpy = 26;
+    private static final int RsBlas_cswap = 27;
+    private static final int RsBlas_ccopy = 28;
+    private static final int RsBlas_caxpy = 29;
+    private static final int RsBlas_zswap = 30;
+    private static final int RsBlas_zcopy = 31;
+    private static final int RsBlas_zaxpy = 32;
+    private static final int RsBlas_srotg = 33;
+    private static final int RsBlas_srotmg = 34;
+    private static final int RsBlas_srot = 35;
+    private static final int RsBlas_srotm = 36;
+    private static final int RsBlas_drotg = 37;
+    private static final int RsBlas_drotmg = 38;
+    private static final int RsBlas_drot = 39;
+    private static final int RsBlas_drotm = 40;
+    private static final int RsBlas_sscal = 41;
+    private static final int RsBlas_dscal = 42;
+    private static final int RsBlas_cscal = 43;
+    private static final int RsBlas_zscal = 44;
+    private static final int RsBlas_csscal = 45;
+    private static final int RsBlas_zdscal = 46;
+    private static final int RsBlas_sgemv = 47;
+    private static final int RsBlas_sgbmv = 48;
+    private static final int RsBlas_strmv = 49;
+    private static final int RsBlas_stbmv = 50;
+    private static final int RsBlas_stpmv = 51;
+    private static final int RsBlas_strsv = 52;
+    private static final int RsBlas_stbsv = 53;
+    private static final int RsBlas_stpsv = 54;
+    private static final int RsBlas_dgemv = 55;
+    private static final int RsBlas_dgbmv = 56;
+    private static final int RsBlas_dtrmv = 57;
+    private static final int RsBlas_dtbmv = 58;
+    private static final int RsBlas_dtpmv = 59;
+    private static final int RsBlas_dtrsv = 60;
+    private static final int RsBlas_dtbsv = 61;
+    private static final int RsBlas_dtpsv = 62;
+    private static final int RsBlas_cgemv = 63;
+    private static final int RsBlas_cgbmv = 64;
+    private static final int RsBlas_ctrmv = 65;
+    private static final int RsBlas_ctbmv = 66;
+    private static final int RsBlas_ctpmv = 67;
+    private static final int RsBlas_ctrsv = 68;
+    private static final int RsBlas_ctbsv = 69;
+    private static final int RsBlas_ctpsv = 70;
+    private static final int RsBlas_zgemv = 71;
+    private static final int RsBlas_zgbmv = 72;
+    private static final int RsBlas_ztrmv = 73;
+    private static final int RsBlas_ztbmv = 74;
+    private static final int RsBlas_ztpmv = 75;
+    private static final int RsBlas_ztrsv = 76;
+    private static final int RsBlas_ztbsv = 77;
+    private static final int RsBlas_ztpsv = 78;
+    private static final int RsBlas_ssymv = 79;
+    private static final int RsBlas_ssbmv = 80;
+    private static final int RsBlas_sspmv = 81;
+    private static final int RsBlas_sger = 82;
+    private static final int RsBlas_ssyr = 83;
+    private static final int RsBlas_sspr = 84;
+    private static final int RsBlas_ssyr2 = 85;
+    private static final int RsBlas_sspr2 = 86;
+    private static final int RsBlas_dsymv = 87;
+    private static final int RsBlas_dsbmv = 88;
+    private static final int RsBlas_dspmv = 89;
+    private static final int RsBlas_dger = 90;
+    private static final int RsBlas_dsyr = 91;
+    private static final int RsBlas_dspr = 92;
+    private static final int RsBlas_dsyr2 = 93;
+    private static final int RsBlas_dspr2 = 94;
+    private static final int RsBlas_chemv = 95;
+    private static final int RsBlas_chbmv = 96;
+    private static final int RsBlas_chpmv = 97;
+    private static final int RsBlas_cgeru = 98;
+    private static final int RsBlas_cgerc = 99;
+    private static final int RsBlas_cher = 100;
+    private static final int RsBlas_chpr = 101;
+    private static final int RsBlas_cher2 = 102;
+    private static final int RsBlas_chpr2 = 103;
+    private static final int RsBlas_zhemv = 104;
+    private static final int RsBlas_zhbmv = 105;
+    private static final int RsBlas_zhpmv = 106;
+    private static final int RsBlas_zgeru = 107;
+    private static final int RsBlas_zgerc = 108;
+    private static final int RsBlas_zher = 109;
+    private static final int RsBlas_zhpr = 110;
+    private static final int RsBlas_zher2 = 111;
+    private static final int RsBlas_zhpr2 = 112;
+    private static final int RsBlas_sgemm = 113;
+    private static final int RsBlas_ssymm = 114;
+    private static final int RsBlas_ssyrk = 115;
+    private static final int RsBlas_ssyr2k = 116;
+    private static final int RsBlas_strmm = 117;
+    private static final int RsBlas_strsm = 118;
+    private static final int RsBlas_dgemm = 119;
+    private static final int RsBlas_dsymm = 120;
+    private static final int RsBlas_dsyrk = 121;
+    private static final int RsBlas_dsyr2k = 122;
+    private static final int RsBlas_dtrmm = 123;
+    private static final int RsBlas_dtrsm = 124;
+    private static final int RsBlas_cgemm = 125;
+    private static final int RsBlas_csymm = 126;
+    private static final int RsBlas_csyrk = 127;
+    private static final int RsBlas_csyr2k = 128;
+    private static final int RsBlas_ctrmm = 129;
+    private static final int RsBlas_ctrsm = 130;
+    private static final int RsBlas_zgemm = 131;
+    private static final int RsBlas_zsymm = 132;
+    private static final int RsBlas_zsyrk = 133;
+    private static final int RsBlas_zsyr2k = 134;
+    private static final int RsBlas_ztrmm = 135;
+    private static final int RsBlas_ztrsm = 136;
+    private static final int RsBlas_chemm = 137;
+    private static final int RsBlas_cherk = 138;
+    private static final int RsBlas_cher2k = 139;
+    private static final int RsBlas_zhemm = 140;
+    private static final int RsBlas_zherk = 141;
+    private static final int RsBlas_zher2k = 142;
+
+    // BLAS extensions start here
+    private static final int RsBlas_bnnm = 1000;
+
+    /**
+     * Create an intrinsic to access BLAS subroutines.
+     *
+     * @param rs The RenderScript context
+     * @return ScriptIntrinsicBLAS
+     */
+    public static ScriptIntrinsicBLAS create(RenderScript rs) {
+        long id = rs.nScriptIntrinsicCreate(13, Element.U32(rs).getID(rs));
+        return new ScriptIntrinsicBLAS(id, rs);
+    }
+
+    /**
+     * @hide
+     */
+    @IntDef({NO_TRANSPOSE, TRANSPOSE, CONJ_TRANSPOSE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Transpose {}
+
+    /**
+     * @hide
+     */
+    @IntDef({UPPER, LOWER})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Uplo {}
+
+    /**
+     * @hide
+     */
+    @IntDef({NON_UNIT, UNIT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Diag {}
+
+    /**
+     * @hide
+     */
+    @IntDef({LEFT, RIGHT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Side {}
+
+    public static final int NO_TRANSPOSE = 111;
+    public static final int TRANSPOSE = 112;
+    public static final int CONJ_TRANSPOSE = 113;
+
+    public static final int UPPER = 121;
+    public static final int LOWER = 122;
+
+    public static final int NON_UNIT = 131;
+    public static final int UNIT = 132;
+
+    public static final int LEFT = 141;
+    public static final int RIGHT = 142;
+
+    static void validateSide(@Side int Side) {
+        if (Side != LEFT && Side != RIGHT) {
+            throw new RSRuntimeException("Invalid side passed to BLAS");
+        }
+    }
+
+    static void validateTranspose(@Transpose int Trans) {
+        if (Trans != NO_TRANSPOSE && Trans != TRANSPOSE &&
+            Trans != CONJ_TRANSPOSE) {
+            throw new RSRuntimeException("Invalid transpose passed to BLAS");
+        }
+    }
+
+    static void validateConjTranspose(@Transpose int Trans) {
+        if (Trans != NO_TRANSPOSE &&
+            Trans != CONJ_TRANSPOSE) {
+            throw new RSRuntimeException("Invalid transpose passed to BLAS");
+        }
+    }
+
+    static void validateDiag(@Diag int Diag) {
+        if (Diag != NON_UNIT && Diag != UNIT) {
+            throw new RSRuntimeException("Invalid diag passed to BLAS");
+        }
+    }
+
+    static void validateUplo(@Uplo int Uplo) {
+        if (Uplo != UPPER && Uplo != LOWER) {
+            throw new RSRuntimeException("Invalid uplo passed to BLAS");
+        }
+    }
+
+
+    /**
+     * Level 2 BLAS
+     */
+
+    static void validateGEMV(Element e, int TransA, Allocation A, Allocation X, int incX, Allocation Y, int incY) {
+        validateTranspose(TransA);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = -1, expectedYDim = -1;
+        if (TransA == NO_TRANSPOSE) {
+            expectedXDim = 1 + (N - 1) * incX;
+            expectedYDim = 1 + (M - 1) * incY;
+        } else {
+            expectedXDim = 1 + (M - 1) * incX;
+            expectedYDim = 1 + (N - 1) * incY;
+        }
+        if (X.getType().getX() != expectedXDim ||
+            Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for GEMV");
+        }
+    }
+
+    /**
+     * SGEMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d58/sgemv_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void SGEMV(@Transpose int TransA, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+        validateGEMV(Element.F32(mRS), TransA, A, X, incX, Y, incY);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DGEMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dc/da8/dgemv_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void DGEMV(@Transpose int TransA, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+        validateGEMV(Element.F64(mRS), TransA, A, X, incX, Y, incY);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CGEMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y   or   y := alpha*A**H*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/d8a/cgemv_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void CGEMV(@Transpose int TransA, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+        validateGEMV(Element.F32_2(mRS), TransA, A, X, incX, Y, incY);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZGEMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y   or   y := alpha*A**H*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d40/zgemv_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void ZGEMV(@Transpose int TransA, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+        validateGEMV(Element.F64_2(mRS), TransA, A, X, incX, Y, incY);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * SGBMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/d46/sgbmv_8f.html
+     *
+     * Note: For a M*N matrix, the input Allocation should also be of size M*N (dimY = M, dimX = N),
+     *       but only the region M*(KL+KU+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert the original matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, m):
+     *              for j in range(max(0, i-kl), min(i+ku+1, n)):
+     *                  b[i, j-i+kl] = a[i, j]
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param KL The number of sub-diagonals of the matrix A.
+     * @param KU The number of super-diagonals of the matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains the band matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void SGBMV(@Transpose int TransA, int KL, int KU, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+        // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+        validateGEMV(Element.F32(mRS), TransA, A, X, incX, Y, incY);
+        if (KL < 0 || KU < 0) {
+            throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+        }
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, KL, KU);
+    }
+
+    /**
+     * DGBMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d2/d3f/dgbmv_8f.html
+     *
+     * Note: For a M*N matrix, the input Allocation should also be of size M*N (dimY = M, dimX = N),
+     *       but only the region M*(KL+KU+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert the original matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, m):
+     *              for j in range(max(0, i-kl), min(i+ku+1, n)):
+     *                  b[i, j-i+kl] = a[i, j]
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param KL The number of sub-diagonals of the matrix A.
+     * @param KU The number of super-diagonals of the matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains the band matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void DGBMV(@Transpose int TransA, int KL, int KU, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+        // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+        validateGEMV(Element.F64(mRS), TransA, A, X, incX, Y, incY);
+        if (KL < 0 || KU < 0) {
+            throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+        }
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, KL, KU);
+    }
+
+    /**
+     * CGBMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y   or   y := alpha*A**H*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/d75/cgbmv_8f.html
+     *
+     * Note: For a M*N matrix, the input Allocation should also be of size M*N (dimY = M, dimX = N),
+     *       but only the region M*(KL+KU+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert the original matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, m):
+     *              for j in range(max(0, i-kl), min(i+ku+1, n)):
+     *                  b[i, j-i+kl] = a[i, j]
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param KL The number of sub-diagonals of the matrix A.
+     * @param KU The number of super-diagonals of the matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains the band matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void CGBMV(@Transpose int TransA, int KL, int KU, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+        // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+        validateGEMV(Element.F32_2(mRS), TransA, A, X, incX, Y, incY);
+        if (KL < 0 || KU < 0) {
+            throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+        }
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, KL, KU);
+    }
+
+    /**
+     * ZGBMV performs one of the matrix-vector operations
+     * y := alpha*A*x + beta*y   or   y := alpha*A**T*x + beta*y   or   y := alpha*A**H*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d9/d46/zgbmv_8f.html
+     *
+     * Note: For a M*N matrix, the input Allocation should also be of size M*N (dimY = M, dimX = N),
+     *       but only the region M*(KL+KU+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert the original matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, m):
+     *              for j in range(max(0, i-kl), min(i+ku+1, n)):
+     *                  b[i, j-i+kl] = a[i, j]
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param KL The number of sub-diagonals of the matrix A.
+     * @param KU The number of super-diagonals of the matrix A.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains the band matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void ZGBMV(@Transpose int TransA, int KL, int KU, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+        // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+        validateGEMV(Element.F64_2(mRS), TransA, A, X, incX, Y, incY);
+        if (KL < 0 || KU < 0) {
+            throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+        }
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, KL, KU);
+    }
+
+    static void validateTRMV(Element e, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+        validateTranspose(TransA);
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        int N = A.getType().getY();
+        if (A.getType().getX() != N) {
+            throw new RSRuntimeException("A must be a square matrix for TRMV");
+        }
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (incX <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for TRMV");
+        }
+    }
+
+    static int validateTPMV(Element e, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+        validateTranspose(TransA);
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        if (!Ap.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (Ap.getType().getY() > 1) {
+            throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+        }
+
+        int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+        //is it really doing anything?
+        if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+            throw new RSRuntimeException("Invalid dimension for Ap");
+        }
+        if (incX <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for TPMV");
+        }
+
+        return N;
+    }
+
+    /**
+     * STRMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/d45/strmv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void STRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+        validateTRMV(Element.F32(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DTRMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dc/d7e/dtrmv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void DTRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+        validateTRMV(Element.F64(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * CTRMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x   or   x := A**H*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/df/d78/ctrmv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void CTRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+        validateTRMV(Element.F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * ZTRMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x   or   x := A**H*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/dd1/ztrmv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void ZTRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+        validateTRMV(Element.F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * STBMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/d7d/stbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void STBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBMV has the same requirements as TRMV + K >= 0
+        if (K < 0) {
+            throw new RSRuntimeException("K must be greater than or equal to 0");
+        }
+        validateTRMV(Element.F32(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DTBMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/df/d29/dtbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void DTBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBMV has the same requirements as TRMV + K >= 0
+        if (K < 0) {
+            throw new RSRuntimeException("K must be greater than or equal to 0");
+        }
+        validateTRMV(Element.F64(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * CTBMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x   or   x := A**H*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/dcd/ctbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void CTBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBMV has the same requirements as TRMV + K >= 0
+        if (K < 0) {
+            throw new RSRuntimeException("K must be greater than or equal to 0");
+        }
+        validateTRMV(Element.F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * ZTBMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x   or   x := A**H*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/d39/ztbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void ZTBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBMV has the same requirements as TRMV + K >= 0
+        if (K < 0) {
+            throw new RSRuntimeException("K must be greater than or equal to 0");
+        }
+        validateTRMV(Element.F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * STPMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/db1/stpmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void STPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        int N = validateTPMV(Element.F32(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DTPMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dc/dcd/dtpmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void DTPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        int N = validateTPMV(Element.F64(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * CTPMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x   or   x := A**H*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/dbb/ctpmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void CTPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        int N = validateTPMV(Element.F32_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * ZTPMV performs one of the matrix-vector operations
+     * x := A*x   or   x := A**T*x   or   x := A**H*x
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d2/d9e/ztpmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void ZTPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        int N = validateTPMV(Element.F64_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * STRSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/d2a/strsv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void STRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation A,  Allocation X,  int incX) {
+        // TRSV is the same as TRMV
+        validateTRMV(Element.F32(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+
+    }
+
+    /**
+     * DTRSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/d96/dtrsv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void DTRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation A,  Allocation X,  int incX) {
+        // TRSV is the same as TRMV
+        validateTRMV(Element.F64(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+
+    }
+
+    /**
+     * CTRSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b   or   A**H*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/dc8/ctrsv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void CTRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation A,  Allocation X,  int incX) {
+        // TRSV is the same as TRMV
+        validateTRMV(Element.F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+
+    }
+
+    /**
+     * ZTRSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b   or   A**H*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d1/d2f/ztrsv_8f.html
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void ZTRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation A,  Allocation X,  int incX) {
+        // TRSV is the same as TRMV
+        validateTRMV(Element.F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+
+    }
+
+    /**
+     * STBSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/d1f/stbsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void STBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBSV is the same as TRMV + K >= 0
+        validateTRMV(Element.F32(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        if (K < 0) {
+            throw new RSRuntimeException("Number of diagonals must be positive");
+        }
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DTBSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/dcf/dtbsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void DTBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBSV is the same as TRMV + K >= 0
+        validateTRMV(Element.F64(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        if (K < 0) {
+            throw new RSRuntimeException("Number of diagonals must be positive");
+        }
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * CTBSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b   or   A**H*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d9/d5f/ctbsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void CTBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBSV is the same as TRMV + K >= 0
+        validateTRMV(Element.F32_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        if (K < 0) {
+            throw new RSRuntimeException("Number of diagonals must be positive");
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * ZTBSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b   or   A**H*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/d5a/ztbsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param K The number of off-diagonals of the matrix A
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void ZTBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  int K, Allocation A,  Allocation X,  int incX) {
+        // TBSV is the same as TRMV + K >= 0
+        validateTRMV(Element.F64_2(mRS), Uplo, TransA, Diag, A, X, incX);
+        int N = A.getType().getY();
+        if (K < 0) {
+            throw new RSRuntimeException("Number of diagonals must be positive");
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * STPSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/d7c/stpsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void STPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        // TPSV is same as TPMV
+        int N = validateTPMV(Element.F32(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DTPSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d9/d84/dtpsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void DTPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        // TPSV is same as TPMV
+        int N = validateTPMV(Element.F64(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * CTPSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b   or   A**H*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/d56/ctpsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void CTPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        // TPSV is same as TPMV
+        int N = validateTPMV(Element.F32_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * ZTPSV solves one of the systems of equations
+     * A*x = b   or   A**T*x = b   or   A**H*x = b
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/da/d57/ztpsv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the matrix is an upper or lower triangular matrix.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param Ap The input allocation contains packed matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     */
+    public void ZTPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag,  Allocation Ap,  Allocation X,  int incX) {
+        // TPSV is same as TPMV
+        int N = validateTPMV(Element.F64_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * Level 2, S and D only
+     */
+    static int validateSYMV(Element e, @Uplo int Uplo, Allocation A, Allocation X, Allocation Y, int incX, int incY) {
+        validateUplo(Uplo);
+        int N = A.getType().getY();
+        if (A.getType().getX() != N) {
+            throw new RSRuntimeException("A must be a square matrix for SYMV");
+        }
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e) ) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SYMV");
+        }
+        int expectedYDim = 1 + (N - 1) * incY;
+        if (Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SYMV");
+        }
+        return N;
+    }
+    static int validateSPMV(Element e, @Uplo int Uplo, Allocation Ap, Allocation X, int incX, Allocation Y, int incY) {
+        validateUplo(Uplo);
+        if (!Ap.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (Ap.getType().getY() > 1) {
+            throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+        }
+
+        int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+        if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+            throw new RSRuntimeException("Invalid dimension for Ap");
+        }
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SPMV");
+        }
+        int expectedYDim = 1 + (N - 1) * incY;
+        if (Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SPMV");
+        }
+
+        return N;
+    }
+    static void validateGER(Element e, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e) ) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+
+        if (N < 1 || M < 1) {
+            throw new RSRuntimeException("M and N must be 1 or greater for GER");
+        }
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (M - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for GER");
+        }
+        int expectedYDim = 1 + (N - 1) * incY;
+        if (Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for GER");
+        }
+
+
+    }
+    static int validateSYR(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation A) {
+        validateUplo(Uplo);
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+
+        int N = A.getType().getX();
+
+        if (X.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+        if (N != A.getType().getY()) {
+            throw new RSRuntimeException("A must be a symmetric matrix");
+        }
+        if (incX <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SYR");
+        }
+        return N;
+    }
+    static int validateSPR(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation Ap) {
+        validateUplo(Uplo);
+        if (!Ap.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (Ap.getType().getY() > 1) {
+            throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+        }
+
+        int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+        if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+            throw new RSRuntimeException("Invalid dimension for Ap");
+        }
+        if (incX <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SPR");
+        }
+
+        return N;
+    }
+
+    static int validateSYR2(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        validateUplo(Uplo);
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        int N = A.getType().getX();
+
+        if (N != A.getType().getY()) {
+            throw new RSRuntimeException("A must be a symmetric matrix");
+        }
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        int expectedYDim = 1 + (N - 1) * incY;
+        if (X.getType().getX() != expectedXDim || Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SYR");
+        }
+        return N;
+
+    }
+    static int validateSPR2(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+        validateUplo(Uplo);
+        if (!Ap.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        if (Ap.getType().getY() > 1) {
+            throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+        }
+
+        int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+        if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+            throw new RSRuntimeException("Invalid dimension for Ap");
+        }
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (N - 1) * incX;
+        int expectedYDim = 1 + (N - 1) * incY;
+        if (X.getType().getX() != expectedXDim || Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for SPR2");
+        }
+
+        return N;
+    }
+
+    /**
+     * SSYMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d2/d94/ssymv_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void SSYMV(@Uplo int Uplo, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+        int N = validateSYMV(Element.F32(mRS), Uplo, A, X, Y, incX, incY);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssymv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * SSBMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/da1/ssbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the band matrix A is being supplied.
+     * @param K The number of off-diagonals of the matrix A
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void SSBMV(@Uplo int Uplo, int K, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+        // SBMV is the same as SYMV + K >= 0
+        if (K < 0) {
+            throw new RSRuntimeException("K must be greater than or equal to 0");
+        }
+        int N = validateSYMV(Element.F32(mRS), Uplo, A, X, Y, incX, incY);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * SSPMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/d68/sspmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the matrix A is supplied in packed form.
+     * @param alpha The scalar alpha.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void SSPMV(@Uplo int Uplo, float alpha, Allocation Ap, Allocation X, int incX, float beta, Allocation Y, int incY) {
+        int N = validateSPMV(Element.F32(mRS), Uplo, Ap, X, incX, Y, incY);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sspmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, Ap.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * SGER performs the rank 1 operation
+     * A := alpha*x*y**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d5c/sger_8f.html
+     *
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     */
+    public void SGER(float alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        validateGER(Element.F32(mRS), X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sger, 0, 0, 0, 0, 0, M, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0.f, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * SSYR performs the rank 1 operation
+     * A := alpha*x*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/dac/ssyr_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     */
+    public void SSYR(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation A) {
+        int N = validateSYR(Element.F32(mRS), Uplo, X, incX, A);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), A.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * SSPR performs the rank 1 operation
+     * A := alpha*x*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d2/d9b/sspr_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     */
+    public void SSPR(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Ap) {
+        int N = validateSPR(Element.F32(mRS), Uplo, X, incX, Ap);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sspr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Ap.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * SSYR2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**T + alpha*y*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d99/ssyr2_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     */
+    public void SSYR2(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        int N = validateSYR2(Element.F32(mRS), Uplo, X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * SSPR2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**T + alpha*y*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d3e/sspr2_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     */
+    public void SSPR2(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+        int N = validateSPR2(Element.F32(mRS), Uplo, X, incX, Y, incY, Ap);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sspr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, Ap.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DSYMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/dbe/dsymv_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void DSYMV(@Uplo int Uplo, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+        int N = validateSYMV(Element.F64(mRS), Uplo, A, X, Y, incX, incY);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsymv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DSBMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/d1e/dsbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the band matrix A is being supplied.
+     * @param K The number of off-diagonals of the matrix A
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void DSBMV(@Uplo int Uplo, int K, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+        // SBMV is the same as SYMV + K >= 0
+        if (K < 0) {
+            throw new RSRuntimeException("K must be greater than or equal to 0");
+        }
+        int N = validateSYMV(Element.F64(mRS), Uplo, A, X, Y, incX, incY);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DSPMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/d85/dspmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the matrix A is supplied in packed form.
+     * @param alpha The scalar alpha.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void DSPMV(@Uplo int Uplo, double alpha, Allocation Ap, Allocation X, int incX, double beta, Allocation Y, int incY) {
+        int N = validateSPMV(Element.F64(mRS), Uplo, Ap, X, incX, Y, incY);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dspmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, Ap.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DGER performs the rank 1 operation
+     * A := alpha*x*y**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dc/da8/dger_8f.html
+     *
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     */
+    public void DGER(double alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        validateGER(Element.F64(mRS), X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dger, 0, 0, 0, 0, 0, M, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0.f, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DSYR performs the rank 1 operation
+     * A := alpha*x*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/d60/dsyr_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     */
+    public void DSYR(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation A) {
+        int N = validateSYR(Element.F64(mRS), Uplo, X, incX, A);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), A.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DSPR performs the rank 1 operation
+     * A := alpha*x*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dd/dba/dspr_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     */
+    public void DSPR(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Ap) {
+        int N = validateSPR(Element.F64(mRS), Uplo, X, incX, Ap);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dspr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Ap.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+    }
+
+    /**
+     * DSYR2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**T + alpha*y*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/d41/dsyr2_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     */
+    public void DSYR2(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        int N = validateSYR2(Element.F64(mRS), Uplo, X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * DSPR2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**T + alpha*y*x**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dd/d9e/dspr2_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     */
+    public void DSPR2(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+        int N = validateSPR2(Element.F64(mRS), Uplo, X, incX, Y, incY, Ap);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dspr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, Ap.getID(mRS), incX, incY, 0, 0);
+    }
+
+
+    /**
+     * Level 2, C and Z only
+     */
+
+    static void validateGERU(Element e, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        if (!A.getType().getElement().isCompatible(e) ||
+            !X.getType().getElement().isCompatible(e) ||
+            !Y.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+            throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+        }
+
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        if (incX <= 0 || incY <= 0) {
+            throw new RSRuntimeException("Vector increments must be greater than 0");
+        }
+        int expectedXDim = 1 + (M - 1) * incX;
+        if (X.getType().getX() != expectedXDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for GERU");
+        }
+        int expectedYDim = 1 + (N - 1) * incY;
+        if (Y.getType().getX() != expectedYDim) {
+            throw new RSRuntimeException("Incorrect vector dimensions for GERU");
+        }
+
+    }
+
+    /**
+     * CHEMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d7/d51/chemv_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void CHEMV(@Uplo int Uplo, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+        // HEMV is the same as SYR2 validation-wise
+        int N = validateSYR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chemv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CHBMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/dc2/chbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the band matrix A is being supplied.
+     * @param K The number of off-diagonals of the matrix A
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void CHBMV(@Uplo int Uplo, int K, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+        // HBMV is the same as SYR2 validation-wise
+        int N = validateSYR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, A);
+        if (K < 0) {
+            throw new RSRuntimeException("K must be 0 or greater for HBMV");
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CHPMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d2/d06/chpmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the matrix A is supplied in packed form.
+     * @param alpha The scalar alpha.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void CHPMV(@Uplo int Uplo, Float2 alpha, Allocation Ap, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+        // HPMV is the same as SPR2
+        int N = validateSPR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, Ap);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chpmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, Ap.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CGERU performs the rank 1 operation
+     * A := alpha*x*y**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d5f/cgeru_8f.html
+     *
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     */
+    public void CGERU(Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        validateGERU(Element.F32_2(mRS), X, incX, Y, incY, A);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgeru, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CGERC performs the rank 1 operation
+     * A := alpha*x*y**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dd/d84/cgerc_8f.html
+     *
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     */
+    public void CGERC(Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        // same as GERU
+        validateGERU(Element.F32_2(mRS), X, incX, Y, incY, A);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgerc, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CHER performs the rank 1 operation
+     * A := alpha*x*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/d6d/cher_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     */
+    public void CHER(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation A) {
+        // same as SYR
+        int N = validateSYR(Element.F32_2(mRS), Uplo, X, incX, A);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cher, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, A.getID(mRS), incX, 0, 0, 0);
+    }
+
+    /**
+     * CHPR performs the rank 1 operation
+     * A := alpha*x*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/dcd/chpr_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     */
+    public void CHPR(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Ap) {
+        // equivalent to SPR for validation
+        int N = validateSPR(Element.F32_2(mRS), Uplo, X, incX, Ap);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chpr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, Ap.getID(mRS), incX, 0, 0, 0);
+    }
+
+    /**
+     * CHER2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**H + alpha*y*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d87/cher2_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     */
+    public void CHER2(@Uplo int Uplo, Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        // same as SYR2
+        int N = validateSYR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cher2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * CHPR2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**H + alpha*y*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/d44/chpr2_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F32_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F32_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     */
+    public void CHPR2(@Uplo int Uplo, Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+        // same as SPR2
+        int N = validateSPR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, Ap);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chpr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, Ap.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZHEMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/ddd/zhemv_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void ZHEMV(@Uplo int Uplo, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+        // HEMV is the same as SYR2 validation-wise
+        int N = validateSYR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhemv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZHBMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/d1a/zhbmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should also be of size N*N (dimY = N, dimX = N),
+     *       but only the region N*(K+1) will be referenced. The following subroutine can is an
+     *       example showing how to convert a UPPER trianglar matrix 'a' to row-based band matrix 'b'.
+     *           for i in range(0, n):
+     *              for j in range(i, min(i+k+1, n)):
+     *                  b[i, j-i] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the band matrix A is being supplied.
+     * @param K The number of off-diagonals of the matrix A
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void ZHBMV(@Uplo int Uplo, int K, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+        // HBMV is the same as SYR2 validation-wise
+        int N = validateSYR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, A);
+        if (K < 0) {
+            throw new RSRuntimeException("K must be 0 or greater for HBMV");
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZHPMV performs the matrix-vector operation
+     * y := alpha*A*x + beta*y
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/d60/zhpmv_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of the matrix A is supplied in packed form.
+     * @param alpha The scalar alpha.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param beta The scalar beta.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     */
+    public void ZHPMV(@Uplo int Uplo, Double2 alpha, Allocation Ap, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+        // HPMV is the same as SPR2
+        int N = validateSPR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, Ap);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhpmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, Ap.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZGERU performs the rank 1 operation
+     * A := alpha*x*y**T + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d7/d12/zgeru_8f.html
+     *
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     */
+    public void ZGERU(Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        validateGERU(Element.F64_2(mRS), X, incX, Y, incY, A);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgeru, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZGERC performs the rank 1 operation
+     * A := alpha*x*y**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/dad/zgerc_8f.html
+     *
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     */
+    public void ZGERC(Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        // same as GERU
+        validateGERU(Element.F64_2(mRS), X, incX, Y, incY, A);
+        int M = A.getType().getY();
+        int N = A.getType().getX();
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgerc, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZHER performs the rank 1 operation
+     * A := alpha*x*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/d0e/zher_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHER(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation A) {
+        // same as SYR
+        int N = validateSYR(Element.F64_2(mRS), Uplo, X, incX, A);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zher, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, A.getID(mRS), incX, 0, 0, 0);
+    }
+
+    /**
+     * ZHPR performs the rank 1 operation
+     * A := alpha*x*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/de1/zhpr_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHPR(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Ap) {
+        // equivalent to SPR for validation
+        int N = validateSPR(Element.F64_2(mRS), Uplo, X, incX, Ap);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhpr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, Ap.getID(mRS), incX, 0, 0, 0);
+    }
+
+    /**
+     * ZHER2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**H + alpha*y*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/da/d8a/zher2_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHER2(@Uplo int Uplo, Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+        // same as SYR2
+        int N = validateSYR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, A);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zher2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+    }
+
+    /**
+     * ZHPR2 performs the symmetric rank 2 operation
+     * A := alpha*x*y**H + alpha*y*x**H + A
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d5/d52/zhpr2_8f.html
+     *
+     * Note: For a N*N matrix, the input Allocation should be a 1D allocation of size dimX = N*(N+1)/2,
+     *       The following subroutine can is an example showing how to convert a UPPER trianglar matrix
+     *       'a' to packed matrix 'b'.
+     *           k = 0
+     *           for i in range(0, n):
+     *              for j in range(i, n):
+     *                  b[k++] = a[i, j]
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part is to be supplied in the packed form.
+     * @param alpha The scalar alpha.
+     * @param X The input allocation contains vector x, supported elements type {@link Element#F64_2}.
+     * @param incX The increment for the elements of vector x, must be larger than zero.
+     * @param Y The input allocation contains vector y, supported elements type {@link Element#F64_2}.
+     * @param incY The increment for the elements of vector y, must be larger than zero.
+     * @param Ap The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHPR2(@Uplo int Uplo, Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+        // same as SPR2
+        int N = validateSPR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, Ap);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhpr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, Ap.getID(mRS), incX, incY, 0, 0);
+    }
+
+
+    /**
+     * Level 3 BLAS
+     */
+
+    static void validateL3(Element e, int TransA, int TransB, int Side, Allocation A, Allocation B, Allocation C) {
+        int aM = -1, aN = -1, bM = -1, bN = -1, cM = -1, cN = -1;
+        if ((A != null && !A.getType().getElement().isCompatible(e)) ||
+            (B != null && !B.getType().getElement().isCompatible(e)) ||
+            (C != null && !C.getType().getElement().isCompatible(e))) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        if (C == null) {
+            //since matrix C is used to store the result, it cannot be null.
+            throw new RSRuntimeException("Allocation C cannot be null");
+        }
+        cM = C.getType().getY();
+        cN = C.getType().getX();
+
+        if (Side == RIGHT) {
+            if ((A == null && B != null) || (A != null && B == null)) {
+                throw new RSRuntimeException("Provided Matrix A without Matrix B, or vice versa");
+            }
+            if (B != null) {
+                bM = A.getType().getY();
+                bN = A.getType().getX();
+            }
+            if (A != null) {
+                aM = B.getType().getY();
+                aN = B.getType().getX();
+            }
+        } else {
+            if (A != null) {
+                if (TransA == TRANSPOSE || TransA == CONJ_TRANSPOSE) {
+                    aN = A.getType().getY();
+                    aM = A.getType().getX();
+                } else {
+                    aM = A.getType().getY();
+                    aN = A.getType().getX();
+                }
+            }
+            if (B != null) {
+                if (TransB == TRANSPOSE || TransB == CONJ_TRANSPOSE) {
+                    bN = B.getType().getY();
+                    bM = B.getType().getX();
+                } else {
+                    bM = B.getType().getY();
+                    bN = B.getType().getX();
+                }
+            }
+        }
+        if (A != null && B != null && C != null) {
+            if (aN != bM || aM != cM || bN != cN) {
+                throw new RSRuntimeException("Called BLAS with invalid dimensions");
+            }
+        } else if (A != null && C != null) {
+            // A and C only, for SYRK
+            if (cM != cN) {
+                throw new RSRuntimeException("Matrix C is not symmetric");
+            }
+            if (aM != cM) {
+                throw new RSRuntimeException("Called BLAS with invalid dimensions");
+            }
+        } else if (A != null && B != null) {
+            // A and B only
+            if (aN != bM) {
+                throw new RSRuntimeException("Called BLAS with invalid dimensions");
+            }
+        }
+
+    }
+
+    /**
+     * SGEMM performs one of the matrix-matrix operations
+     * C := alpha*op(A)*op(B) + beta*C   where op(X) is one of op(X) = X  or  op(X) = X**T
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/de2/sgemm_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param TransB The type of transpose applied to matrix B.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32}.
+     */
+    public void SGEMM(@Transpose int TransA, @Transpose int TransB, float alpha, Allocation A,
+                      Allocation B, float beta, Allocation C) {
+        validateTranspose(TransA);
+        validateTranspose(TransB);
+        validateL3(Element.F32(mRS), TransA, TransB, 0, A, B, C);
+
+        int M = -1, N = -1, K = -1;
+        if (TransA != NO_TRANSPOSE) {
+            M = A.getType().getX();
+            K = A.getType().getY();
+        } else {
+            M = A.getType().getY();
+            K = A.getType().getX();
+        }
+        if (TransB != NO_TRANSPOSE) {
+            N = B.getType().getY();
+        } else {
+            N = B.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sgemm, TransA, TransB, 0, 0, 0, M, N, K,  alpha, A.getID(mRS), B.getID(mRS),
+                                        beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * DGEMM performs one of the matrix-matrix operations
+     * C := alpha*op(A)*op(B) + beta*C   where op(X) is one of op(X) = X  or  op(X) = X**T
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d7/d2b/dgemm_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param TransB The type of transpose applied to matrix B.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64}.
+     */
+    public void DGEMM(@Transpose int TransA, @Transpose int TransB, double alpha, Allocation A,
+                      Allocation B, double beta, Allocation C) {
+        validateTranspose(TransA);
+        validateTranspose(TransB);
+        validateL3(Element.F64(mRS), TransA, TransB, 0, A, B, C);
+        int M = -1, N = -1, K = -1;
+        if (TransA != NO_TRANSPOSE) {
+            M = A.getType().getX();
+            K = A.getType().getY();
+        } else {
+            M = A.getType().getY();
+            K = A.getType().getX();
+        }
+        if (TransB != NO_TRANSPOSE) {
+            N = B.getType().getY();
+        } else {
+            N = B.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dgemm, TransA, TransB, 0, 0, 0, M, N, K,  alpha, A.getID(mRS), B.getID(mRS),
+                                        beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * CGEMM performs one of the matrix-matrix operations
+     * C := alpha*op(A)*op(B) + beta*C   where op(X) is one of op(X) = X  or  op(X) = X**T  or  op(X) = X**H
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/d5b/cgemm_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param TransB The type of transpose applied to matrix B.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CGEMM(@Transpose int TransA, @Transpose int TransB, Float2 alpha, Allocation A,
+                      Allocation B, Float2 beta, Allocation C) {
+        validateTranspose(TransA);
+        validateTranspose(TransB);
+        validateL3(Element.F32_2(mRS), TransA, TransB, 0, A, B, C);
+        int M = -1, N = -1, K = -1;
+        if (TransA != NO_TRANSPOSE) {
+            M = A.getType().getX();
+            K = A.getType().getY();
+        } else {
+            M = A.getType().getY();
+            K = A.getType().getX();
+        }
+        if (TransB != NO_TRANSPOSE) {
+            N = B.getType().getY();
+        } else {
+            N = B.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgemm, TransA, TransB, 0, 0, 0, M, N, K,  alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+                                         beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZGEMM performs one of the matrix-matrix operations
+     * C := alpha*op(A)*op(B) + beta*C   where op(X) is one of op(X) = X  or  op(X) = X**T  or  op(X) = X**H
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d7/d76/zgemm_8f.html
+     *
+     * @param TransA The type of transpose applied to matrix A.
+     * @param TransB The type of transpose applied to matrix B.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZGEMM(@Transpose int TransA, @Transpose int TransB, Double2 alpha, Allocation A,
+                      Allocation B, Double2 beta, Allocation C) {
+        validateTranspose(TransA);
+        validateTranspose(TransB);
+        validateL3(Element.F64_2(mRS), TransA, TransB, 0, A, B, C);
+        int M = -1, N = -1, K = -1;
+        if (TransA != NO_TRANSPOSE) {
+            M = A.getType().getX();
+            K = A.getType().getY();
+        } else {
+            M = A.getType().getY();
+            K = A.getType().getX();
+        }
+        if (TransB != NO_TRANSPOSE) {
+            N = B.getType().getY();
+        } else {
+            N = B.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgemm, TransA, TransB, 0, 0, 0, M, N, K,  alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+                                   beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * SSYMM performs one of the matrix-matrix operations
+     * C := alpha*A*B + beta*C   or   C := alpha*B*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d7/d42/ssymm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32}.
+     */
+    public void SSYMM(@Side int Side, @Uplo int Uplo, float alpha, Allocation A,
+                      Allocation B, float beta, Allocation C) {
+        validateSide(Side);
+        validateUplo(Uplo);
+        //For SYMM, Matrix A should be symmetric
+        if (A.getType().getX() != A.getType().getY()) {
+            throw new RSRuntimeException("Matrix A is not symmetric");
+        }
+        validateL3(Element.F32(mRS), 0, 0, Side, A, B, C);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha, A.getID(mRS), B.getID(mRS),
+                                        beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * DSYMM performs one of the matrix-matrix operations
+     * C := alpha*A*B + beta*C   or   C := alpha*B*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/db0/dsymm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64}.
+     */
+    public void DSYMM(@Side int Side, @Uplo int Uplo, double alpha, Allocation A,
+                      Allocation B, double beta, Allocation C) {
+        validateSide(Side);
+        validateUplo(Uplo);
+        if (A.getType().getX() != A.getType().getY()) {
+            throw new RSRuntimeException("Matrix A is not symmetric");
+        }
+        validateL3(Element.F64(mRS), 0, 0, Side, A, B, C);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha, A.getID(mRS), B.getID(mRS),
+                                        beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * CSYMM performs one of the matrix-matrix operations
+     * C := alpha*A*B + beta*C   or   C := alpha*B*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/db/d59/csymm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CSYMM(@Side int Side, @Uplo int Uplo, Float2 alpha, Allocation A,
+                      Allocation B, Float2 beta, Allocation C) {
+        validateSide(Side);
+        validateUplo(Uplo);
+        if (A.getType().getX() != A.getType().getY()) {
+            throw new RSRuntimeException("Matrix A is not symmetric");
+        }
+        validateL3(Element.F32_2(mRS), 0, 0, Side, A, B, C);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+                                         beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZSYMM performs one of the matrix-matrix operations
+     * C := alpha*A*B + beta*C   or   C := alpha*B*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/df/d51/zsymm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZSYMM(@Side int Side, @Uplo int Uplo, Double2 alpha, Allocation A,
+                      Allocation B, Double2 beta, Allocation C) {
+        validateSide(Side);
+        validateUplo(Uplo);
+        if (A.getType().getX() != A.getType().getY()) {
+            throw new RSRuntimeException("Matrix A is not symmetric");
+        }
+        validateL3(Element.F64_2(mRS), 0, 0, Side, A, B, C);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+                                   beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * SSYRK performs one of the symmetric rank k operations
+     * C := alpha*A*A**T + beta*C   or   C := alpha*A**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d0/d40/ssyrk_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32}.
+     */
+    public void SSYRK(@Uplo int Uplo, @Transpose int Trans, float alpha, Allocation A, float beta, Allocation C) {
+        validateTranspose(Trans);
+        validateUplo(Uplo);
+        validateL3(Element.F32(mRS), Trans, 0, 0, A, null, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), 0, beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * DSYRK performs one of the symmetric rank k operations
+     * C := alpha*A*A**T + beta*C   or   C := alpha*A**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dc/d05/dsyrk_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64}.
+     */
+    public void DSYRK(@Uplo int Uplo, @Transpose int Trans, double alpha, Allocation A, double beta, Allocation C) {
+        validateTranspose(Trans);
+        validateUplo(Uplo);
+        validateL3(Element.F64(mRS), Trans, 0, 0, A, null, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), 0, beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * CSYRK performs one of the symmetric rank k operations
+     * C := alpha*A*A**T + beta*C   or   C := alpha*A**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/d6a/csyrk_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CSYRK(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Float2 beta, Allocation C) {
+        validateTranspose(Trans);
+        validateUplo(Uplo);
+        validateL3(Element.F32_2(mRS), Trans, 0, 0, A, null, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), 0, beta.x, beta.y,
+                                         C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZSYRK performs one of the symmetric rank k operations
+     * C := alpha*A*A**T + beta*C   or   C := alpha*A**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/d54/zsyrk_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZSYRK(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Double2 beta, Allocation C) {
+        validateTranspose(Trans);
+        validateUplo(Uplo);
+        validateL3(Element.F64_2(mRS), Trans, 0, 0, A, null, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), 0, beta.x, beta.y,
+                                   C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    static void validateSYR2K(Element e, @Transpose int Trans, Allocation A, Allocation B, Allocation C) {
+        validateTranspose(Trans);
+        if (!A.getType().getElement().isCompatible(e) ||
+            !B.getType().getElement().isCompatible(e) ||
+            !C.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        int Cdim = -1;
+        // A is n x k if no transpose, k x n if transpose
+        // C is n x n
+        if (Trans == TRANSPOSE) {
+            // check columns versus C
+            Cdim = A.getType().getX();
+        } else {
+            // check rows versus C
+            Cdim = A.getType().getY();
+        }
+        if (C.getType().getX() != Cdim || C.getType().getY() != Cdim) {
+            throw new RSRuntimeException("Invalid symmetric matrix in SYR2K");
+        }
+        // A dims == B dims
+        if (A.getType().getX() != B.getType().getX() || A.getType().getY() != B.getType().getY()) {
+            throw new RSRuntimeException("Invalid A and B in SYR2K");
+        }
+    }
+
+    /**
+     * SSYR2K performs one of the symmetric rank 2k operations
+     * C := alpha*A*B**T + alpha*B*A**T + beta*C   or   C := alpha*A**T*B + alpha*B**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/df/d3d/ssyr2k_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32}.
+     */
+    public void SSYR2K(@Uplo int Uplo, @Transpose int Trans, float alpha, Allocation A, Allocation B, float beta, Allocation C) {
+        validateUplo(Uplo);
+        validateSYR2K(Element.F32(mRS), Trans, A, B, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * DSYR2K performs one of the symmetric rank 2k operations
+     * C := alpha*A*B**T + alpha*B*A**T + beta*C   or   C := alpha*A**T*B + alpha*B**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d1/dec/dsyr2k_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64}.
+     */
+    public void DSYR2K(@Uplo int Uplo, @Transpose int Trans, double alpha, Allocation A, Allocation B, double beta, Allocation C) {
+        validateUplo(Uplo);
+        validateSYR2K(Element.F64(mRS), Trans, A, B, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * CSYR2K performs one of the symmetric rank 2k operations
+     * C := alpha*A*B**T + alpha*B*A**T + beta*C   or   C := alpha*A**T*B + alpha*B**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/d7e/csyr2k_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CSYR2K(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Allocation B, Float2 beta, Allocation C) {
+        validateUplo(Uplo);
+        validateSYR2K(Element.F32_2(mRS), Trans, A, B, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZSYR2K performs one of the symmetric rank 2k operations
+     * C := alpha*A*B**T + alpha*B*A**T + beta*C   or   C := alpha*A**T*B + alpha*B**T*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/df/d20/zsyr2k_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZSYR2K(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Allocation B, Double2 beta, Allocation C) {
+        validateUplo(Uplo);
+        validateSYR2K(Element.F64_2(mRS), Trans, A, B, C);
+        int K = -1;
+        if (Trans != NO_TRANSPOSE) {
+            K = A.getType().getY();
+        } else {
+            K = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    static void validateTRMM(Element e, @Side int Side, @Transpose int TransA, Allocation A, Allocation B) {
+        validateSide(Side);
+        validateTranspose(TransA);
+        int aM = -1, aN = -1, bM = -1, bN = -1;
+        if (!A.getType().getElement().isCompatible(e) ||
+            !B.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+
+        aM = A.getType().getY();
+        aN = A.getType().getX();
+        if (aM != aN) {
+            throw new RSRuntimeException("Called TRMM with a non-symmetric matrix A");
+        }
+
+        bM = B.getType().getY();
+        bN = B.getType().getX();
+        if (Side == LEFT) {
+            if (aN != bM) {
+                throw new RSRuntimeException("Called TRMM with invalid matrices");
+            }
+        } else {
+            if (bN != aM) {
+                throw new RSRuntimeException("Called TRMM with invalid matrices");
+            }
+        }
+    }
+
+    /**
+     * STRMM performs one of the matrix-matrix operations
+     * B := alpha*op(A)*B   or   B := alpha*B*op(A)
+     * op(A) is one of  op(A) = A  or  op(A) = A**T
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/df/d01/strmm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32}.
+     */
+    public void STRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, float alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRMM(Element.F32(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                        alpha, A.getID(mRS), B.getID(mRS), 0.f, 0, 0, 0, 0, 0);
+    }
+
+    /**
+     * DTRMM performs one of the matrix-matrix operations
+     * B := alpha*op(A)*B   or   B := alpha*B*op(A)
+     * op(A) is one of  op(A) = A  or  op(A) = A**T
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/dd/d19/dtrmm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64}.
+     */
+    public void DTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, double alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRMM(Element.F64(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                        alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
+    }
+
+    /**
+     * CTRMM performs one of the matrix-matrix operations
+     * B := alpha*op(A)*B   or   B := alpha*B*op(A)
+     * op(A) is one of  op(A) = A  or  op(A) = A**T  or  op(A) = A**H
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d4/d9b/ctrmm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     */
+    public void CTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRMM(Element.F32_2(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                         alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+    }
+
+    /**
+     * ZTRMM performs one of the matrix-matrix operations
+     * B := alpha*op(A)*B   or   B := alpha*B*op(A)
+     * op(A) is one of  op(A) = A  or  op(A) = A**T  or  op(A) = A**H
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/de1/ztrmm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     */
+    public void ZTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRMM(Element.F64_2(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                   alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+    }
+
+    static void validateTRSM(Element e, @Side int Side, @Transpose int TransA, Allocation A, Allocation B) {
+        int adim = -1, bM = -1, bN = -1;
+        validateSide(Side);
+        validateTranspose(TransA);
+        if (!A.getType().getElement().isCompatible(e) ||
+            !B.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        adim = A.getType().getX();
+        if (adim != A.getType().getY()) {
+            // this may be unnecessary, the restriction could potentially be relaxed
+            // A needs to contain at least that symmetric matrix but could theoretically be larger
+            // for now we assume adapters are sufficient, will reevaluate in the future
+            throw new RSRuntimeException("Called TRSM with a non-symmetric matrix A");
+        }
+        bM = B.getType().getY();
+        bN = B.getType().getX();
+        if (Side == LEFT) {
+            // A is M*M
+            if (adim != bM) {
+                throw new RSRuntimeException("Called TRSM with invalid matrix dimensions");
+            }
+        } else {
+            // A is N*N
+            if (adim != bN) {
+                throw new RSRuntimeException("Called TRSM with invalid matrix dimensions");
+            }
+        }
+    }
+
+    /**
+     * STRSM solves one of the matrix equations
+     * op(A)*X := alpha*B   or   X*op(A) := alpha*B
+     * op(A) is one of  op(A) = A  or  op(A) = A**T
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d2/d8b/strsm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32}.
+     */
+    public void STRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, float alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRSM(Element.F32(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                        alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
+    }
+
+    /**
+     * DTRSM solves one of the matrix equations
+     * op(A)*X := alpha*B   or   X*op(A) := alpha*B
+     * op(A) is one of  op(A) = A  or  op(A) = A**T
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/da7/dtrsm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64}.
+     */
+    public void DTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, double alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRSM(Element.F64(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                        alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
+    }
+
+    /**
+     * CTRSM solves one of the matrix equations
+     * op(A)*X := alpha*B   or   X*op(A) := alpha*B
+     * op(A) is one of  op(A) = A  or  op(A) = A**T  or  op(A) = A**H
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/de/d30/ctrsm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     */
+    public void CTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRSM(Element.F32_2(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                         alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+    }
+
+    /**
+     * ZTRSM solves one of the matrix equations
+     * op(A)*X := alpha*B   or   X*op(A) := alpha*B
+     * op(A) is one of  op(A) = A  or  op(A) = A**T  or  op(A) = A**H
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d1/d39/ztrsm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether matrix A is upper or lower triangular.
+     * @param TransA The type of transpose applied to matrix A.
+     * @param Diag Specifies whether or not A is unit triangular.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     */
+    public void ZTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
+        validateUplo(Uplo);
+        validateDiag(Diag);
+        validateTRSM(Element.F64_2(mRS), Side, TransA, A, B);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                   alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+    }
+
+    static void validateHEMM(Element e, @Side int Side, Allocation A, Allocation B, Allocation C) {
+        validateSide(Side);
+
+        if (!A.getType().getElement().isCompatible(e) ||
+            !B.getType().getElement().isCompatible(e) ||
+            !C.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+
+        // A must be square; can potentially be relaxed similar to TRSM
+        int adim = A.getType().getX();
+        if (adim != A.getType().getY()) {
+            throw new RSRuntimeException("Called HEMM with non-square A");
+        }
+        if ((Side == LEFT && adim != B.getType().getY()) ||
+            (Side == RIGHT && adim != B.getType().getX())) {
+            throw new RSRuntimeException("Called HEMM with invalid B");
+        }
+        if (B.getType().getX() != C.getType().getX() ||
+            B.getType().getY() != C.getType().getY()) {
+            throw new RSRuntimeException("Called HEMM with mismatched B and C");
+        }
+    }
+
+    /**
+     * CHEMM performs one of the matrix-matrix operations
+     * C := alpha*A*B + beta*C   or   C := alpha*B*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d3/d66/chemm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CHEMM(@Side int Side, @Uplo int Uplo, Float2 alpha, Allocation A, Allocation B, Float2 beta, Allocation C) {
+        validateUplo(Uplo);
+        validateHEMM(Element.F32_2(mRS), Side, A, B, C);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chemm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0,
+                                         alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZHEMM performs one of the matrix-matrix operations
+     * C := alpha*A*B + beta*C   or   C := alpha*B*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d6/d3e/zhemm_8f.html
+     *
+     * @param Side Specifies whether the symmetric matrix A appears on the left or right.
+     * @param Uplo Specifies whether the upper or lower triangular part is to be referenced.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHEMM(@Side int Side, @Uplo int Uplo, Double2 alpha, Allocation A, Allocation B, Double2 beta, Allocation C) {
+        validateUplo(Uplo);
+        validateHEMM(Element.F64_2(mRS), Side, A, B, C);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhemm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0,
+                                   alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    static void validateHERK(Element e, @Transpose int Trans, Allocation A, Allocation C) {
+        if (!A.getType().getElement().isCompatible(e) ||
+            !C.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        validateConjTranspose(Trans);
+        int cdim = C.getType().getX();
+        if (cdim != C.getType().getY()) {
+            throw new RSRuntimeException("Called HERK with non-square C");
+        }
+        if (Trans == NO_TRANSPOSE) {
+            if (cdim != A.getType().getY()) {
+                throw new RSRuntimeException("Called HERK with invalid A");
+            }
+        } else {
+            if (cdim != A.getType().getX()) {
+                throw new RSRuntimeException("Called HERK with invalid A");
+            }
+        }
+    }
+
+    /**
+     * CHERK performs one of the hermitian rank k operations
+     * C := alpha*A*A**H + beta*C   or   C := alpha*A**H*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d8/d52/cherk_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CHERK(@Uplo int Uplo, @Transpose int Trans, float alpha, Allocation A, float beta, Allocation C) {
+        validateUplo(Uplo);
+        validateHERK(Element.F32_2(mRS), Trans, A, C);
+        int k = 0;
+        if (Trans == CONJ_TRANSPOSE) {
+            k = A.getType().getY();
+        } else {
+            k = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cherk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k,
+                                         alpha, 0, A.getID(mRS), 0, beta, 0, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZHERK performs one of the hermitian rank k operations
+     * C := alpha*A*A**H + beta*C   or   C := alpha*A**H*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d1/db1/zherk_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHERK(@Uplo int Uplo, @Transpose int Trans, double alpha, Allocation A, double beta, Allocation C) {
+        validateUplo(Uplo);
+        validateHERK(Element.F64_2(mRS), Trans, A, C);
+        int k = 0;
+        if (Trans == CONJ_TRANSPOSE) {
+            k = A.getType().getY();
+        } else {
+            k = A.getType().getX();
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zherk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k,
+                                   alpha, 0, A.getID(mRS), 0, beta, 0, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    static void validateHER2K(Element e, @Transpose int Trans, Allocation A, Allocation B, Allocation C) {
+        if (!A.getType().getElement().isCompatible(e) ||
+            !B.getType().getElement().isCompatible(e) ||
+            !C.getType().getElement().isCompatible(e)) {
+            throw new RSRuntimeException("Called BLAS with wrong Element type");
+        }
+        validateConjTranspose(Trans);
+        int cdim = C.getType().getX();
+        if (cdim != C.getType().getY()) {
+            throw new RSRuntimeException("Called HER2K with non-square C");
+        }
+        if (Trans == NO_TRANSPOSE) {
+            if (A.getType().getY() != cdim) {
+                throw new RSRuntimeException("Called HER2K with invalid matrices");
+            }
+        } else {
+            if (A.getType().getX() != cdim) {
+                throw new RSRuntimeException("Called HER2K with invalid matrices");
+            }
+        }
+        if (A.getType().getX() != B.getType().getX() || A.getType().getY() != B.getType().getY()) {
+            throw new RSRuntimeException("Called HER2K with invalid A and B matrices");
+        }
+    }
+
+    /**
+     * CHER2K performs one of the hermitian rank 2k operations
+     * C := alpha*A*B**H + conjg( alpha )*B*A**H + beta*C   or   C := alpha*A**H*B + conjg( alpha )*B**H*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d1/d82/cher2k_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F32_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F32_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F32_2}.
+     */
+    public void CHER2K(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Allocation B, float beta, Allocation C) {
+        validateUplo(Uplo);
+        validateHER2K(Element.F32_2(mRS), Trans, A, B, C);
+        int k = 0;
+        if (Trans == NO_TRANSPOSE) {
+            k = A.getType().getX();
+        } else {
+            k = A.getType().getY();
+        }
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cher2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k, alpha.x, alpha.y,
+                                         A.getID(mRS), B.getID(mRS), beta, 0, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+    /**
+     * ZHER2K performs one of the hermitian rank 2k operations
+     * C := alpha*A*B**H + conjg( alpha )*B*A**H + beta*C   or   C := alpha*A**H*B + conjg( alpha )*B**H*A + beta*C
+     *
+     * Details: http://www.netlib.org/lapack/explore-html/d7/dfa/zher2k_8f.html
+     *
+     * @param Uplo Specifies whether the upper or lower triangular part of C is to be referenced.
+     * @param Trans The type of transpose applied to the operation.
+     * @param alpha The scalar alpha.
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
+     * @param beta The scalar beta.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
+     */
+    public void ZHER2K(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Allocation B, double beta, Allocation C) {
+        validateUplo(Uplo);
+        validateHER2K(Element.F64_2(mRS), Trans, A, B, C);
+        int k = 0;
+        if (Trans == NO_TRANSPOSE) {
+            k = A.getType().getX();
+        } else {
+            k = A.getType().getY();
+        }
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zher2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k, alpha.x, alpha.y,
+                                   A.getID(mRS), B.getID(mRS), beta, 0, C.getID(mRS), 0, 0, 0, 0);
+    }
+
+
+    /**
+     * 8-bit GEMM-like operation for neural networks: C = A * Transpose(B)
+     * Calculations are done in 1.10.21 fixed-point format for the final output,
+     * just before there's a shift down to drop the fractional parts. The output
+     * values are gated to 0 to 255 to fit in a byte, but the 10-bit format
+     * gives some headroom to avoid wrapping around on small overflows.
+     *
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#U8}.
+     * @param a_offset The offset for all values in matrix A, e.g A[i,j] = A[i,j] - a_offset. Value should be from 0 to 255.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#U8}.
+     * @param b_offset The offset for all values in matrix B, e.g B[i,j] = B[i,j] - b_offset. Value should be from 0 to 255.
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#U8}.
+     * @param c_offset The offset for all values in matrix C.
+     * @param c_mult The multiplier for all values in matrix C, e.g C[i,j] = (C[i,j] + c_offset) * c_mult.
+     **/
+    public void BNNM(Allocation A, int a_offset, Allocation B, int b_offset, Allocation C, int c_offset, int c_mult) {
+        validateL3(Element.U8(mRS), NO_TRANSPOSE, TRANSPOSE, 0, A, B, C);
+
+        if (a_offset < 0 || a_offset > 255) {
+            throw new RSRuntimeException("Invalid a_offset passed to BNNM");
+        }
+        if (b_offset < 0 || b_offset > 255) {
+            throw new RSRuntimeException("Invalid b_offset passed to BNNM");
+        }
+        int M = -1, N = -1, K = -1;
+        M = A.getType().getY();
+        N = B.getType().getY();
+        K = A.getType().getX();
+
+
+        mRS.nScriptIntrinsicBLAS_BNNM(getID(mRS), M, N, K, A.getID(mRS), a_offset, B.getID(mRS), b_offset, C.getID(mRS), c_offset, c_mult);
+
+    }
+
+}
diff --git a/android/renderscript/ScriptIntrinsicBlend.java b/android/renderscript/ScriptIntrinsicBlend.java
new file mode 100644
index 0000000..a1c79ef
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicBlend.java
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Intrinsic kernels for blending two {@link android.renderscript.Allocation} objects.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class ScriptIntrinsicBlend extends ScriptIntrinsic {
+    ScriptIntrinsicBlend(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for inputs and outputs
+     *
+     * @return ScriptIntrinsicBlend
+     */
+    public static ScriptIntrinsicBlend create(RenderScript rs, Element e) {
+        // 7 comes from RS_SCRIPT_INTRINSIC_ID_BLEND in rsDefines.h
+        long id = rs.nScriptIntrinsicCreate(7, e.getID(rs));
+        return new ScriptIntrinsicBlend(id, rs);
+
+    }
+
+    private void blend(int id, Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        if (!ain.getElement().isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Input is not of expected format.");
+        }
+        if (!aout.getElement().isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Output is not of expected format.");
+        }
+        forEach(id, ain, aout, null, opt);
+    }
+
+    /**
+     * Sets dst = {0, 0, 0, 0}
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachClear(Allocation ain, Allocation aout) {
+        forEachClear(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = {0, 0, 0, 0}
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachClear(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(0, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the Clear kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDClear() {
+        return createKernelID(0, 3, null, null);
+    }
+
+
+    /**
+     * Sets dst = src
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrc(Allocation ain, Allocation aout) {
+        forEachSrc(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = src
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachSrc(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(1, ain, aout, null);
+    }
+
+    /**
+     * Get a KernelID for the Src kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrc() {
+        return createKernelID(1, 3, null, null);
+    }
+
+    /**
+     * Sets dst = dst
+     *
+     * This is a NOP.
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDst(Allocation ain, Allocation aout) {
+        // NOP
+    }
+
+    /**
+     * Sets dst = dst
+     *
+     * This is a NOP.
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachDst(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        // N, optOP
+    }
+
+    /**
+     * Get a KernelID for the Dst kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDst() {
+        return createKernelID(2, 3, null, null);
+    }
+
+    /**
+     * Sets dst = src + dst * (1.0 - src.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcOver(Allocation ain, Allocation aout) {
+        forEachSrcOver(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = src + dst * (1.0 - src.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachSrcOver(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(3, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the SrcOver kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcOver() {
+        return createKernelID(3, 3, null, null);
+    }
+
+    /**
+     * Sets dst = dst + src * (1.0 - dst.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstOver(Allocation ain, Allocation aout) {
+        forEachDstOver(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = dst + src * (1.0 - dst.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachDstOver(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(4, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the DstOver kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstOver() {
+        return createKernelID(4, 3, null, null);
+    }
+
+    /**
+     * Sets dst = src * dst.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcIn(Allocation ain, Allocation aout) {
+        forEachSrcIn(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = src * dst.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachSrcIn(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(5, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the SrcIn kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcIn() {
+        return createKernelID(5, 3, null, null);
+    }
+
+    /**
+     * Sets dst = dst * src.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstIn(Allocation ain, Allocation aout) {
+        forEachDstIn(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = dst * src.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachDstIn(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(6, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the DstIn kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstIn() {
+        return createKernelID(6, 3, null, null);
+    }
+
+    /**
+     * Sets dst = src * (1.0 - dst.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcOut(Allocation ain, Allocation aout) {
+        forEachSrcOut(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = src * (1.0 - dst.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachSrcOut(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(7, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the SrcOut kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcOut() {
+        return createKernelID(7, 3, null, null);
+    }
+
+    /**
+     * Sets dst = dst * (1.0 - src.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstOut(Allocation ain, Allocation aout) {
+        forEachDstOut(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = dst * (1.0 - src.a)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachDstOut(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(8, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the DstOut kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstOut() {
+        return createKernelID(8, 3, null, null);
+    }
+
+    /**
+     * dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb
+     * dst.a = dst.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSrcAtop(Allocation ain, Allocation aout) {
+        forEachSrcAtop(ain, aout, null);
+    }
+
+    /**
+     * dst.rgb = src.rgb * dst.a + (1.0 - src.a) * dst.rgb
+     * dst.a = dst.a
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachSrcAtop(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(9, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the SrcAtop kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSrcAtop() {
+        return createKernelID(9, 3, null, null);
+    }
+
+    /**
+     * dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb
+     * dst.a = src.a
+     * Note: Before API 23, the alpha channel was not correctly set.
+     *       Please use with caution when targeting older APIs.
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachDstAtop(Allocation ain, Allocation aout) {
+        forEachDstAtop(ain, aout, null);
+    }
+
+    /**
+     * dst = dst.rgb * src.a + (1.0 - dst.a) * src.rgb
+     * dst.a = src.a
+     * Note: Before API 23, the alpha channel was not correctly set.
+     *       Please use with caution when targeting older APIs.
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachDstAtop(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(10, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the DstAtop kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDDstAtop() {
+        return createKernelID(10, 3, null, null);
+    }
+
+    /**
+     * Sets dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachXor(Allocation ain, Allocation aout) {
+        forEachXor(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = {src.r ^ dst.r, src.g ^ dst.g, src.b ^ dst.b, src.a ^ dst.a}
+     *
+     * <b>Note:</b> this is NOT the Porter/Duff XOR mode; this is a bitwise xor.
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachXor(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(11, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the Xor kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDXor() {
+        return createKernelID(11, 3, null, null);
+    }
+
+    ////////
+/*
+    public void forEachNormal(Allocation ain, Allocation aout) {
+        blend(12, ain, aout);
+    }
+
+    public void forEachAverage(Allocation ain, Allocation aout) {
+        blend(13, ain, aout);
+    }
+*/
+    /**
+     * Sets dst = src * dst
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachMultiply(Allocation ain, Allocation aout) {
+        forEachMultiply(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = src * dst
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachMultiply(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(14, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the Multiply kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDMultiply() {
+        return createKernelID(14, 3, null, null);
+    }
+
+/*
+    public void forEachScreen(Allocation ain, Allocation aout) {
+        blend(15, ain, aout);
+    }
+
+    public void forEachDarken(Allocation ain, Allocation aout) {
+        blend(16, ain, aout);
+    }
+
+    public void forEachLighten(Allocation ain, Allocation aout) {
+        blend(17, ain, aout);
+    }
+
+    public void forEachOverlay(Allocation ain, Allocation aout) {
+        blend(18, ain, aout);
+    }
+
+    public void forEachHardlight(Allocation ain, Allocation aout) {
+        blend(19, ain, aout);
+    }
+
+    public void forEachSoftlight(Allocation ain, Allocation aout) {
+        blend(20, ain, aout);
+    }
+
+    public void forEachDifference(Allocation ain, Allocation aout) {
+        blend(21, ain, aout);
+    }
+
+    public void forEachNegation(Allocation ain, Allocation aout) {
+        blend(22, ain, aout);
+    }
+
+    public void forEachExclusion(Allocation ain, Allocation aout) {
+        blend(23, ain, aout);
+    }
+
+    public void forEachColorDodge(Allocation ain, Allocation aout) {
+        blend(24, ain, aout);
+    }
+
+    public void forEachInverseColorDodge(Allocation ain, Allocation aout) {
+        blend(25, ain, aout);
+    }
+
+    public void forEachSoftDodge(Allocation ain, Allocation aout) {
+        blend(26, ain, aout);
+    }
+
+    public void forEachColorBurn(Allocation ain, Allocation aout) {
+        blend(27, ain, aout);
+    }
+
+    public void forEachInverseColorBurn(Allocation ain, Allocation aout) {
+        blend(28, ain, aout);
+    }
+
+    public void forEachSoftBurn(Allocation ain, Allocation aout) {
+        blend(29, ain, aout);
+    }
+
+    public void forEachReflect(Allocation ain, Allocation aout) {
+        blend(30, ain, aout);
+    }
+
+    public void forEachGlow(Allocation ain, Allocation aout) {
+        blend(31, ain, aout);
+    }
+
+    public void forEachFreeze(Allocation ain, Allocation aout) {
+        blend(32, ain, aout);
+    }
+
+    public void forEachHeat(Allocation ain, Allocation aout) {
+        blend(33, ain, aout);
+    }
+*/
+    /**
+     * Sets dst = min(src + dst, 1.0)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachAdd(Allocation ain, Allocation aout) {
+        forEachAdd(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = min(src + dst, 1.0)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachAdd(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(34, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the Add kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDAdd() {
+        return createKernelID(34, 3, null, null);
+    }
+
+    /**
+     * Sets dst = max(dst - src, 0.0)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     */
+    public void forEachSubtract(Allocation ain, Allocation aout) {
+        forEachSubtract(ain, aout, null);
+    }
+
+    /**
+     * Sets dst = max(dst - src, 0.0)
+     *
+     * @param ain The source buffer
+     * @param aout The destination buffer
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEachSubtract(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        blend(35, ain, aout, opt);
+    }
+
+    /**
+     * Get a KernelID for the Subtract kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelIDSubtract() {
+        return createKernelID(35, 3, null, null);
+    }
+
+/*
+    public void forEachStamp(Allocation ain, Allocation aout) {
+        blend(36, ain, aout);
+    }
+
+    public void forEachRed(Allocation ain, Allocation aout) {
+        blend(37, ain, aout);
+    }
+
+    public void forEachGreen(Allocation ain, Allocation aout) {
+        blend(38, ain, aout);
+    }
+
+    public void forEachBlue(Allocation ain, Allocation aout) {
+        blend(39, ain, aout);
+    }
+
+    public void forEachHue(Allocation ain, Allocation aout) {
+        blend(40, ain, aout);
+    }
+
+    public void forEachSaturation(Allocation ain, Allocation aout) {
+        blend(41, ain, aout);
+    }
+
+    public void forEachColor(Allocation ain, Allocation aout) {
+        blend(42, ain, aout);
+    }
+
+    public void forEachLuminosity(Allocation ain, Allocation aout) {
+        blend(43, ain, aout);
+    }
+*/
+}
+
diff --git a/android/renderscript/ScriptIntrinsicBlur.java b/android/renderscript/ScriptIntrinsicBlur.java
new file mode 100644
index 0000000..68cbc3f
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicBlur.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic Gausian blur filter. Applies a gaussian blur of the
+ * specified radius to all elements of an allocation.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicBlur extends ScriptIntrinsic {
+    private final float[] mValues = new float[9];
+    private Allocation mInput;
+
+    private ScriptIntrinsicBlur(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for applying a blur to an allocation. The
+     * default radius is 5.0.
+     *
+     * Supported elements types are {@link Element#U8},
+     * {@link Element#U8_4}.
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for inputs and outputs
+     *
+     * @return ScriptIntrinsicBlur
+     */
+    public static ScriptIntrinsicBlur create(RenderScript rs, Element e) {
+        if ((!e.isCompatible(Element.U8_4(rs))) && (!e.isCompatible(Element.U8(rs)))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+        long id = rs.nScriptIntrinsicCreate(5, e.getID(rs));
+        ScriptIntrinsicBlur sib = new ScriptIntrinsicBlur(id, rs);
+        sib.setRadius(5.f);
+        return sib;
+    }
+
+    /**
+     * Set the input of the blur.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation
+     */
+    public void setInput(Allocation ain) {
+        if (ain.getType().getY() == 0) {
+            throw new RSIllegalArgumentException("Input set to a 1D Allocation");
+        }
+        Element e = ain.getElement();
+        if ((!e.isCompatible(Element.U8_4(mRS))) && (!e.isCompatible(Element.U8(mRS)))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+        mInput = ain;
+        setVar(1, ain);
+    }
+
+    /**
+     * Set the radius of the Blur.
+     *
+     * Supported range 0 < radius <= 25
+     *
+     * @param radius The radius of the blur
+     */
+    public void setRadius(float radius) {
+        if (radius <= 0 || radius > 25) {
+            throw new RSIllegalArgumentException("Radius out of range (0 < r <= 25).");
+        }
+        setVar(0, radius);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        if (aout.getType().getY() == 0) {
+            throw new RSIllegalArgumentException("Output is a 1D Allocation");
+        }
+        forEach(0, (Allocation) null, aout, null);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach(Allocation aout, Script.LaunchOptions opt) {
+        if (aout.getType().getY() == 0) {
+            throw new RSIllegalArgumentException("Output is a 1D Allocation");
+        }
+        forEach(0, (Allocation) null, aout, null, opt);
+    }
+
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+}
diff --git a/android/renderscript/ScriptIntrinsicColorMatrix.java b/android/renderscript/ScriptIntrinsicColorMatrix.java
new file mode 100644
index 0000000..4a05cf5
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic for applying a color matrix to allocations.
+ *
+ * If the element type is {@link Element.DataType#UNSIGNED_8},
+ * it is converted to {@link Element.DataType#FLOAT_32} and
+ * normalized from (0-255) to (0-1). If the incoming vector size
+ * is less than four, a {@link Element#F32_4} is created by
+ * filling the missing vector channels with zero. This value is
+ * then multiplied by the 4x4 color matrix as performed by
+ * rsMatrixMultiply(), adding a {@link Element#F32_4}, and then
+ * writing it to the output {@link Allocation}.
+ *
+ * If the ouptut type is unsigned, the value is normalized from
+ * (0-1) to (0-255) and converted. If the output vector size is
+ * less than four, the unused channels are discarded.
+ *
+ * Supported elements types are {@link Element#U8}, {@link
+ * Element#U8_2}, {@link Element#U8_3}, {@link Element#U8_4},
+ * {@link Element#F32}, {@link Element#F32_2}, {@link
+ * Element#F32_3}, and {@link Element#F32_4}.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicColorMatrix extends ScriptIntrinsic {
+    private final Matrix4f mMatrix = new Matrix4f();
+    private final Float4 mAdd = new Float4();
+
+    private ScriptIntrinsicColorMatrix(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for applying a color matrix to an
+     * allocation.
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for inputs and outputs, As of API 19,
+     *          this parameter is ignored. The Element type check is
+     *          performed in the kernel launch.
+     *
+     * @deprecated Use the single argument version as Element is now
+     *             ignored.
+     *
+     * @return ScriptIntrinsicColorMatrix
+     */
+    @Deprecated
+    public static ScriptIntrinsicColorMatrix create(RenderScript rs, Element e) {
+        return create(rs);
+    }
+
+    /**
+     * Create an intrinsic for applying a color matrix to an
+     * allocation.
+     *
+     * @param rs The RenderScript context
+     *
+     * @return ScriptIntrinsicColorMatrix
+     */
+    public static ScriptIntrinsicColorMatrix create(RenderScript rs) {
+        long id = rs.nScriptIntrinsicCreate(2, 0);
+        return new ScriptIntrinsicColorMatrix(id, rs);
+
+    }
+
+    private void setMatrix() {
+        FieldPacker fp = new FieldPacker(16*4);
+        fp.addMatrix(mMatrix);
+        setVar(0, fp);
+    }
+
+    /**
+     * Set the color matrix which will be applied to each cell of
+     * the image.
+     *
+     * @param m The 4x4 matrix to set.
+     */
+    public void setColorMatrix(Matrix4f m) {
+        mMatrix.load(m);
+        setMatrix();
+    }
+
+    /**
+     * Set the color matrix which will be applied to each cell of the image.
+     * This will set the alpha channel to be a copy.
+     *
+     * @param m The 3x3 matrix to set.
+     */
+    public void setColorMatrix(Matrix3f m) {
+        mMatrix.load(m);
+        setMatrix();
+    }
+
+    /**
+     * Set the value to be added after the color matrix has been
+     * applied. The default value is {0, 0, 0, 0}
+     *
+     * @param f The float4 value to be added.
+     */
+    public void setAdd(Float4 f) {
+        mAdd.x = f.x;
+        mAdd.y = f.y;
+        mAdd.z = f.z;
+        mAdd.w = f.w;
+
+        FieldPacker fp = new FieldPacker(4*4);
+        fp.addF32(f.x);
+        fp.addF32(f.y);
+        fp.addF32(f.z);
+        fp.addF32(f.w);
+        setVar(1, fp);
+    }
+
+    /**
+     * Set the value to be added after the color matrix has been
+     * applied. The default value is {0, 0, 0, 0}
+     *
+     * @param r The red add value.
+     * @param g The green add value.
+     * @param b The blue add value.
+     * @param a The alpha add value.
+     */
+    public void setAdd(float r, float g, float b, float a) {
+        mAdd.x = r;
+        mAdd.y = g;
+        mAdd.z = b;
+        mAdd.w = a;
+
+        FieldPacker fp = new FieldPacker(4*4);
+        fp.addF32(mAdd.x);
+        fp.addF32(mAdd.y);
+        fp.addF32(mAdd.z);
+        fp.addF32(mAdd.w);
+        setVar(1, fp);
+    }
+
+    /**
+     * Set a color matrix to convert from RGB to luminance. The alpha channel
+     * will be a copy.
+     *
+     */
+    public void setGreyscale() {
+        mMatrix.loadIdentity();
+        mMatrix.set(0, 0, 0.299f);
+        mMatrix.set(1, 0, 0.587f);
+        mMatrix.set(2, 0, 0.114f);
+        mMatrix.set(0, 1, 0.299f);
+        mMatrix.set(1, 1, 0.587f);
+        mMatrix.set(2, 1, 0.114f);
+        mMatrix.set(0, 2, 0.299f);
+        mMatrix.set(1, 2, 0.587f);
+        mMatrix.set(2, 2, 0.114f);
+        setMatrix();
+    }
+
+    /**
+     * Set the matrix to convert from YUV to RGB with a direct copy of the 4th
+     * channel.
+     *
+     */
+    public void setYUVtoRGB() {
+        mMatrix.loadIdentity();
+        mMatrix.set(0, 0, 1.f);
+        mMatrix.set(1, 0, 0.f);
+        mMatrix.set(2, 0, 1.13983f);
+        mMatrix.set(0, 1, 1.f);
+        mMatrix.set(1, 1, -0.39465f);
+        mMatrix.set(2, 1, -0.5806f);
+        mMatrix.set(0, 2, 1.f);
+        mMatrix.set(1, 2, 2.03211f);
+        mMatrix.set(2, 2, 0.f);
+        setMatrix();
+    }
+
+    /**
+     * Set the matrix to convert from RGB to YUV with a direct copy of the 4th
+     * channel.
+     *
+     */
+    public void setRGBtoYUV() {
+        mMatrix.loadIdentity();
+        mMatrix.set(0, 0, 0.299f);
+        mMatrix.set(1, 0, 0.587f);
+        mMatrix.set(2, 0, 0.114f);
+        mMatrix.set(0, 1, -0.14713f);
+        mMatrix.set(1, 1, -0.28886f);
+        mMatrix.set(2, 1, 0.436f);
+        mMatrix.set(0, 2, 0.615f);
+        mMatrix.set(1, 2, -0.51499f);
+        mMatrix.set(2, 2, -0.10001f);
+        setMatrix();
+    }
+
+    /**
+     * Invoke the kernel and apply the matrix to each cell of input
+     * {@link Allocation} and copy to the output {@link Allocation}.
+     *
+     * If the vector size of the input is less than four, the
+     * remaining components are treated as zero for the matrix
+     * multiply.
+     *
+     * If the output vector size is less than four, the unused
+     * vector components are discarded.
+     *
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     */
+    public void forEach(Allocation ain, Allocation aout) {
+        forEach(ain, aout, null);
+    }
+
+    /**
+     * Invoke the kernel and apply the matrix to each cell of input
+     * {@link Allocation} and copy to the output {@link Allocation}.
+     *
+     * If the vector size of the input is less than four, the
+     * remaining components are treated as zero for the matrix
+     * multiply.
+     *
+     * If the output vector size is less than four, the unused
+     * vector components are discarded.
+     *
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        if (!ain.getElement().isCompatible(Element.U8(mRS)) &&
+            !ain.getElement().isCompatible(Element.U8_2(mRS)) &&
+            !ain.getElement().isCompatible(Element.U8_3(mRS)) &&
+            !ain.getElement().isCompatible(Element.U8_4(mRS)) &&
+            !ain.getElement().isCompatible(Element.F32(mRS)) &&
+            !ain.getElement().isCompatible(Element.F32_2(mRS)) &&
+            !ain.getElement().isCompatible(Element.F32_3(mRS)) &&
+            !ain.getElement().isCompatible(Element.F32_4(mRS))) {
+
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+
+        if (!aout.getElement().isCompatible(Element.U8(mRS)) &&
+            !aout.getElement().isCompatible(Element.U8_2(mRS)) &&
+            !aout.getElement().isCompatible(Element.U8_3(mRS)) &&
+            !aout.getElement().isCompatible(Element.U8_4(mRS)) &&
+            !aout.getElement().isCompatible(Element.F32(mRS)) &&
+            !aout.getElement().isCompatible(Element.F32_2(mRS)) &&
+            !aout.getElement().isCompatible(Element.F32_3(mRS)) &&
+            !aout.getElement().isCompatible(Element.F32_4(mRS))) {
+
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+
+        forEach(0, ain, aout, null, opt);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
+
+}
+
diff --git a/android/renderscript/ScriptIntrinsicConvolve3x3.java b/android/renderscript/ScriptIntrinsicConvolve3x3.java
new file mode 100644
index 0000000..4b9dff1
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic for applying a 3x3 convolve to an allocation.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicConvolve3x3 extends ScriptIntrinsic {
+    private final float[] mValues = new float[9];
+    private Allocation mInput;
+
+    private ScriptIntrinsicConvolve3x3(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8}, {@link
+     * Element#U8_2}, {@link Element#U8_3}, {@link Element#U8_4},
+     * {@link Element#F32}, {@link Element#F32_2}, {@link
+     * Element#F32_3}, and {@link Element#F32_4}.
+     *
+     * <p> The default coefficients are:
+     * <code>
+     * <p> [ 0,  0,  0 ]
+     * <p> [ 0,  1,  0 ]
+     * <p> [ 0,  0,  0 ]
+     * </code>
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicConvolve3x3
+     */
+    public static ScriptIntrinsicConvolve3x3 create(RenderScript rs, Element e) {
+        float f[] = { 0, 0, 0, 0, 1, 0, 0, 0, 0};
+        if (!e.isCompatible(Element.U8(rs)) &&
+            !e.isCompatible(Element.U8_2(rs)) &&
+            !e.isCompatible(Element.U8_3(rs)) &&
+            !e.isCompatible(Element.U8_4(rs)) &&
+            !e.isCompatible(Element.F32(rs)) &&
+            !e.isCompatible(Element.F32_2(rs)) &&
+            !e.isCompatible(Element.F32_3(rs)) &&
+            !e.isCompatible(Element.F32_4(rs))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+        long id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
+        ScriptIntrinsicConvolve3x3 si = new ScriptIntrinsicConvolve3x3(id, rs);
+        si.setCoefficients(f);
+        return si;
+
+    }
+
+    /**
+     * Set the input of the 3x3 convolve.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(1, ain);
+    }
+
+    /**
+     * Set the coefficients for the convolve.
+     *
+     * <p> The convolve layout is:
+     * <code>
+     * <p> [ 0,  1,  2 ]
+     * <p> [ 3,  4,  5 ]
+     * <p> [ 6,  7,  8 ]
+     * </code>
+     *
+     * @param v The array of coefficients to set
+     */
+    public void setCoefficients(float v[]) {
+        FieldPacker fp = new FieldPacker(9*4);
+        for (int ct=0; ct < mValues.length; ct++) {
+            mValues[ct] = v[ct];
+            fp.addF32(mValues[ct]);
+        }
+        setVar(0, fp);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, (Allocation) null, aout, null);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach(Allocation aout, Script.LaunchOptions opt) {
+        forEach(0, (Allocation) null, aout, null, opt);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+
+}
diff --git a/android/renderscript/ScriptIntrinsicConvolve5x5.java b/android/renderscript/ScriptIntrinsicConvolve5x5.java
new file mode 100644
index 0000000..ed93c7e
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic for applying a 5x5 convolve to an allocation.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicConvolve5x5 extends ScriptIntrinsic {
+    private final float[] mValues = new float[25];
+    private Allocation mInput;
+
+    private ScriptIntrinsicConvolve5x5(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8}, {@link
+     * Element#U8_2}, {@link Element#U8_3}, {@link Element#U8_4},
+     * {@link Element#F32}, {@link Element#F32_2}, {@link
+     * Element#F32_3}, and {@link Element#F32_4}.
+     *
+     * <p> The default coefficients are:
+     * <code>
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * <p> [ 0,  0,  1,  0,  0  ]
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * <p> [ 0,  0,  0,  0,  0  ]
+     * </code>
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicConvolve5x5
+     */
+    public static ScriptIntrinsicConvolve5x5 create(RenderScript rs, Element e) {
+        if (!e.isCompatible(Element.U8(rs)) &&
+            !e.isCompatible(Element.U8_2(rs)) &&
+            !e.isCompatible(Element.U8_3(rs)) &&
+            !e.isCompatible(Element.U8_4(rs)) &&
+            !e.isCompatible(Element.F32(rs)) &&
+            !e.isCompatible(Element.F32_2(rs)) &&
+            !e.isCompatible(Element.F32_3(rs)) &&
+            !e.isCompatible(Element.F32_4(rs))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+
+        long id = rs.nScriptIntrinsicCreate(4, e.getID(rs));
+        return new ScriptIntrinsicConvolve5x5(id, rs);
+
+    }
+
+    /**
+     * Set the input of the 5x5 convolve.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(1, ain);
+    }
+
+    /**
+    * Set the coefficients for the convolve.
+    *
+    * <p> The convolve layout is:
+    * <code>
+    * <p> [ 0,  1,  2,  3,  4  ]
+    * <p> [ 5,  6,  7,  8,  9  ]
+    * <p> [ 10, 11, 12, 13, 14 ]
+    * <p> [ 15, 16, 17, 18, 19 ]
+    * <p> [ 20, 21, 22, 23, 24 ]
+    * </code>
+    *
+    * @param v The array of coefficients to set
+    */
+    public void setCoefficients(float v[]) {
+        FieldPacker fp = new FieldPacker(25*4);
+        for (int ct=0; ct < mValues.length; ct++) {
+            mValues[ct] = v[ct];
+            fp.addF32(mValues[ct]);
+        }
+        setVar(0, fp);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, (Allocation) null, aout, null);
+    }
+
+    /**
+     * Apply the filter to the input and save to the specified
+     * allocation.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach(Allocation aout, Script.LaunchOptions opt) {
+        forEach(0, (Allocation) null, aout, null, opt);
+    }
+
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+}
diff --git a/android/renderscript/ScriptIntrinsicHistogram.java b/android/renderscript/ScriptIntrinsicHistogram.java
new file mode 100644
index 0000000..4a71bc8
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicHistogram.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic Histogram filter.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicHistogram extends ScriptIntrinsic {
+    private Allocation mOut;
+
+    private ScriptIntrinsicHistogram(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for calculating the histogram of an uchar
+     * or uchar4 image.
+     *
+     * Supported elements types are
+     * {@link Element#U8_4}, {@link Element#U8_3},
+     * {@link Element#U8_2}, {@link Element#U8}
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for inputs
+     *
+     * @return ScriptIntrinsicHistogram
+     */
+    public static ScriptIntrinsicHistogram create(RenderScript rs, Element e) {
+        if ((!e.isCompatible(Element.U8_4(rs))) &&
+            (!e.isCompatible(Element.U8_3(rs))) &&
+            (!e.isCompatible(Element.U8_2(rs))) &&
+            (!e.isCompatible(Element.U8(rs)))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+        long id = rs.nScriptIntrinsicCreate(9, e.getID(rs));
+        ScriptIntrinsicHistogram sib = new ScriptIntrinsicHistogram(id, rs);
+        return sib;
+    }
+
+    /**
+     * Process an input buffer and place the histogram into the
+     * output allocation. The output allocation may be a narrower
+     * vector size than the input. In this case the vector size of
+     * the output is used to determine how many of the input
+     * channels are used in the computation. This is useful if you
+     * have an RGBA input buffer but only want the histogram for
+     * RGB.
+     *
+     * 1D and 2D input allocations are supported.
+     *
+     * @param ain The input image
+     */
+    public void forEach(Allocation ain) {
+        forEach(ain, null);
+    }
+
+    /**
+     * Process an input buffer and place the histogram into the
+     * output allocation. The output allocation may be a narrower
+     * vector size than the input. In this case the vector size of
+     * the output is used to determine how many of the input
+     * channels are used in the computation. This is useful if you
+     * have an RGBA input buffer but only want the histogram for
+     * RGB.
+     *
+     * 1D and 2D input allocations are supported.
+     *
+     * @param ain The input image
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach(Allocation ain, Script.LaunchOptions opt) {
+        if (ain.getType().getElement().getVectorSize() <
+            mOut.getType().getElement().getVectorSize()) {
+
+            throw new RSIllegalArgumentException(
+                "Input vector size must be >= output vector size.");
+        }
+        if (!ain.getType().getElement().isCompatible(Element.U8(mRS)) &&
+            !ain.getType().getElement().isCompatible(Element.U8_2(mRS)) &&
+            !ain.getType().getElement().isCompatible(Element.U8_3(mRS)) &&
+            !ain.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Input type must be U8, U8_1, U8_2 or U8_4.");
+        }
+
+        forEach(0, ain, null, null, opt);
+    }
+
+
+
+    /**
+     * Set the coefficients used for the RGBA to Luminocity
+     * calculation. The default is {0.299f, 0.587f, 0.114f, 0.f}.
+     *
+     * Coefficients must be >= 0 and sum to 1.0 or less.
+     *
+     * @param r Red coefficient
+     * @param g Green coefficient
+     * @param b Blue coefficient
+     * @param a Alpha coefficient
+     */
+    public void setDotCoefficients(float r, float g, float b, float a) {
+        if ((r < 0.f) || (g < 0.f) || (b < 0.f) || (a < 0.f)) {
+            throw new RSIllegalArgumentException("Coefficient may not be negative.");
+        }
+        if ((r + g + b + a) > 1.f) {
+            throw new RSIllegalArgumentException("Sum of coefficients must be 1.0 or less.");
+        }
+
+        FieldPacker fp = new FieldPacker(16);
+        fp.addF32(r);
+        fp.addF32(g);
+        fp.addF32(b);
+        fp.addF32(a);
+        setVar(0, fp);
+    }
+
+    /**
+     * Set the output of the histogram.  32 bit integer types are
+     * supported.
+     *
+     * @param aout The output allocation
+     */
+    public void setOutput(Allocation aout) {
+        mOut = aout;
+        if (mOut.getType().getElement() != Element.U32(mRS) &&
+            mOut.getType().getElement() != Element.U32_2(mRS) &&
+            mOut.getType().getElement() != Element.U32_3(mRS) &&
+            mOut.getType().getElement() != Element.U32_4(mRS) &&
+            mOut.getType().getElement() != Element.I32(mRS) &&
+            mOut.getType().getElement() != Element.I32_2(mRS) &&
+            mOut.getType().getElement() != Element.I32_3(mRS) &&
+            mOut.getType().getElement() != Element.I32_4(mRS)) {
+
+            throw new RSIllegalArgumentException("Output type must be U32 or I32.");
+        }
+        if ((mOut.getType().getX() != 256) ||
+            (mOut.getType().getY() != 0) ||
+            mOut.getType().hasMipmaps() ||
+            (mOut.getType().getYuv() != 0)) {
+
+            throw new RSIllegalArgumentException("Output must be 1D, 256 elements.");
+        }
+        setVar(1, aout);
+    }
+
+
+    /**
+     * Process an input buffer and place the histogram into the
+     * output allocation. The dot product of the input channel and
+     * the coefficients from 'setDotCoefficients' are used to
+     * calculate the output values.
+     *
+     * 1D and 2D input allocations are supported.
+     *
+     * @param ain The input image
+     */
+    public void forEach_Dot(Allocation ain) {
+        forEach_Dot(ain, null);
+    }
+
+    /**
+     * Process an input buffer and place the histogram into the
+     * output allocation. The dot product of the input channel and
+     * the coefficients from 'setDotCoefficients' are used to
+     * calculate the output values.
+     *
+     * 1D and 2D input allocations are supported.
+     *
+     * @param ain The input image
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach_Dot(Allocation ain, Script.LaunchOptions opt) {
+        if (mOut.getType().getElement().getVectorSize() != 1) {
+            throw new RSIllegalArgumentException("Output vector size must be one.");
+        }
+        if (!ain.getType().getElement().isCompatible(Element.U8(mRS)) &&
+            !ain.getType().getElement().isCompatible(Element.U8_2(mRS)) &&
+            !ain.getType().getElement().isCompatible(Element.U8_3(mRS)) &&
+            !ain.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Input type must be U8, U8_1, U8_2 or U8_4.");
+        }
+
+        forEach(1, ain, null, null, opt);
+    }
+
+
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID_Separate() {
+        return createKernelID(0, 3, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+}
+
diff --git a/android/renderscript/ScriptIntrinsicLUT.java b/android/renderscript/ScriptIntrinsicLUT.java
new file mode 100644
index 0000000..7d5b09f
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicLUT.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic for applying a per-channel lookup table. Each
+ * channel of the input has an independant lookup table. The
+ * tables are 256 entries in size and can cover the full value
+ * range of {@link Element#U8_4}.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public final class ScriptIntrinsicLUT extends ScriptIntrinsic {
+    private final Matrix4f mMatrix = new Matrix4f();
+    private Allocation mTables;
+    private final byte mCache[] = new byte[1024];
+    private boolean mDirty = true;
+
+    private ScriptIntrinsicLUT(long id, RenderScript rs) {
+        super(id, rs);
+        mTables = Allocation.createSized(rs, Element.U8(rs), 1024);
+        for (int ct=0; ct < 256; ct++) {
+            mCache[ct] = (byte)ct;
+            mCache[ct + 256] = (byte)ct;
+            mCache[ct + 512] = (byte)ct;
+            mCache[ct + 768] = (byte)ct;
+        }
+        setVar(0, mTables);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * The defaults tables are identity.
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for intputs and outputs
+     *
+     * @return ScriptIntrinsicLUT
+     */
+    public static ScriptIntrinsicLUT create(RenderScript rs, Element e) {
+        long id = rs.nScriptIntrinsicCreate(3, e.getID(rs));
+        return new ScriptIntrinsicLUT(id, rs);
+
+    }
+
+    public void destroy() {
+        mTables.destroy();
+        super.destroy();
+    }
+
+    private void validate(int index, int value) {
+        if (index < 0 || index > 255) {
+            throw new RSIllegalArgumentException("Index out of range (0-255).");
+        }
+        if (value < 0 || value > 255) {
+            throw new RSIllegalArgumentException("Value out of range (0-255).");
+        }
+    }
+
+    /**
+     * Set an entry in the red channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setRed(int index, int value) {
+        validate(index, value);
+        mCache[index] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Set an entry in the green channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setGreen(int index, int value) {
+        validate(index, value);
+        mCache[index+256] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Set an entry in the blue channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setBlue(int index, int value) {
+        validate(index, value);
+        mCache[index+512] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Set an entry in the alpha channel lookup table
+     *
+     * @param index Must be 0-255
+     * @param value Must be 0-255
+     */
+    public void setAlpha(int index, int value) {
+        validate(index, value);
+        mCache[index+768] = (byte)value;
+        mDirty = true;
+    }
+
+    /**
+     * Invoke the kernel and apply the lookup to each cell of ain
+     * and copy to aout.
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     */
+    public void forEach(Allocation ain, Allocation aout) {
+        forEach(ain, aout, null);
+    }
+
+    /**
+     * Invoke the kernel and apply the lookup to each cell of ain
+     * and copy to aout.
+     *
+     * @param ain Input allocation
+     * @param aout Output allocation
+     * @param opt Options for clipping
+     */
+    public void forEach(Allocation ain, Allocation aout, Script.LaunchOptions opt) {
+        if (mDirty) {
+            mDirty = false;
+            mTables.copyFromUnchecked(mCache);
+        }
+        forEach(0, ain, aout, null, opt);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
+}
+
diff --git a/android/renderscript/ScriptIntrinsicResize.java b/android/renderscript/ScriptIntrinsicResize.java
new file mode 100644
index 0000000..a87fe95
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicResize.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic for performing a resize of a 2D allocation.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public final class ScriptIntrinsicResize extends ScriptIntrinsic {
+    private Allocation mInput;
+
+    private ScriptIntrinsicResize(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8}, {@link
+     * Element#U8_2}, {@link Element#U8_3}, {@link Element#U8_4}
+     * {@link Element#F32}, {@link Element#F32_2}, {@link
+     * Element#F32_3}, {@link Element#F32_4}
+     *
+     * @param rs The RenderScript context
+     *
+     * @return ScriptIntrinsicResize
+     */
+    public static ScriptIntrinsicResize create(RenderScript rs) {
+        long id = rs.nScriptIntrinsicCreate(12, 0);
+        ScriptIntrinsicResize si = new ScriptIntrinsicResize(id, rs);
+        return si;
+
+    }
+
+    /**
+     * Set the input of the resize.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        Element e = ain.getElement();
+        if (!e.isCompatible(Element.U8(mRS)) &&
+            !e.isCompatible(Element.U8_2(mRS)) &&
+            !e.isCompatible(Element.U8_3(mRS)) &&
+            !e.isCompatible(Element.U8_4(mRS)) &&
+            !e.isCompatible(Element.F32(mRS)) &&
+            !e.isCompatible(Element.F32_2(mRS)) &&
+            !e.isCompatible(Element.F32_3(mRS)) &&
+            !e.isCompatible(Element.F32_4(mRS))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
+
+        mInput = ain;
+        setVar(0, ain);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(0, null);
+    }
+
+
+    /**
+     * Resize copy the input allocation to the output specified. The
+     * Allocation is rescaled if necessary using bi-cubic
+     * interpolation.
+     *
+     * @param aout Output allocation. Element type must match
+     *             current input.  Must not be same as input.
+     */
+    public void forEach_bicubic(Allocation aout) {
+        if (aout == mInput) {
+            throw new RSIllegalArgumentException("Output cannot be same as Input.");
+        }
+        forEach_bicubic(aout, null);
+    }
+
+    /**
+     * Resize copy the input allocation to the output specified. The
+     * Allocation is rescaled if necessary using bi-cubic
+     * interpolation.
+     *
+     * @param aout Output allocation. Element type must match
+     *             current input.
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach_bicubic(Allocation aout, Script.LaunchOptions opt) {
+        forEach(0, (Allocation) null, aout, null, opt);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID_bicubic() {
+        return createKernelID(0, 2, null, null);
+    }
+
+
+}
diff --git a/android/renderscript/ScriptIntrinsicYuvToRGB.java b/android/renderscript/ScriptIntrinsicYuvToRGB.java
new file mode 100644
index 0000000..a94f916
--- /dev/null
+++ b/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Intrinsic for converting an Android YUV buffer to RGB.
+ *
+ * The input allocation should be supplied in a supported YUV format
+ * as a YUV element Allocation. The output is RGBA; the alpha channel
+ * will be set to 255.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public final class ScriptIntrinsicYuvToRGB extends ScriptIntrinsic {
+    private Allocation mInput;
+
+    ScriptIntrinsicYuvToRGB(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Create an intrinsic for converting YUV to RGB.
+     *
+     * Supported elements types are {@link Element#U8_4}
+     *
+     * @param rs The RenderScript context
+     * @param e Element type for output
+     *
+     * @return ScriptIntrinsicYuvToRGB
+     */
+    public static ScriptIntrinsicYuvToRGB create(RenderScript rs, Element e) {
+        // 6 comes from RS_SCRIPT_INTRINSIC_YUV_TO_RGB in rsDefines.h
+        long id = rs.nScriptIntrinsicCreate(6, e.getID(rs));
+        ScriptIntrinsicYuvToRGB si = new ScriptIntrinsicYuvToRGB(id, rs);
+        return si;
+    }
+
+
+    /**
+     * Set the input yuv allocation, must be {@link Element#U8}.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        setVar(0, ain);
+    }
+
+    /**
+     * Convert the image to RGB.
+     *
+     * @param aout Output allocation. Must match creation element
+     *             type.
+     */
+    public void forEach(Allocation aout) {
+        forEach(0, (Allocation) null, aout, null);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(0, null);
+    }
+}
diff --git a/android/renderscript/Short2.java b/android/renderscript/Short2.java
new file mode 100644
index 0000000..4565eb4
--- /dev/null
+++ b/android/renderscript/Short2.java
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+/**
+ * Class for exposing the native RenderScript Short2 type back to the Android system.
+ *
+ * Vector version of the basic short type.
+ * Provides two short fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Short2 {
+    public short x;
+    public short y;
+
+    public Short2() {
+    }
+
+    /** @hide */
+    public Short2(short i) {
+        this.x = this.y = i;
+    }
+
+    public Short2(short x, short y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /** @hide */
+    public Short2(Short2 source) {
+        this.x = source.x;
+        this.y = source.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Short2 a) {
+        this.x += a.x;
+        this.y += a.y;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 add(Short2 a, Short2 b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x + b.x);
+        result.y = (short)(a.y + b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(short value) {
+        x += value;
+        y += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 add(Short2 a, short b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x + b);
+        result.y = (short)(a.y + b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Short2 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 sub(Short2 a, Short2 b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x - b.x);
+        result.y = (short)(a.y - b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(short value) {
+        x -= value;
+        y -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 sub(Short2 a, short b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x - b);
+        result.y = (short)(a.y - b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Short2 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 mul(Short2 a, Short2 b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x * b.x);
+        result.y = (short)(a.y * b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(short value) {
+        x *= value;
+        y *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 mul(Short2 a, short b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x * b);
+        result.y = (short)(a.y * b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Short2 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 div(Short2 a, Short2 b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x / b.x);
+        result.y = (short)(a.y / b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(short value) {
+        x /= value;
+        y /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 div(Short2 a, short b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x / b);
+        result.y = (short)(a.y / b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Short2 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 mod(Short2 a, Short2 b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x % b.x);
+        result.y = (short)(a.y % b.y);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(short value) {
+        x %= value;
+        y %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short2 mod(Short2 a, short b) {
+        Short2 result = new Short2();
+        result.x = (short)(a.x % b);
+        result.y = (short)(a.y % b);
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public short length() {
+        return 2;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = (short)(-x);
+        this.y = (short)(-y);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public short dotProduct(Short2 a) {
+        return (short)((x * a.x) + (y * a.y));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static short dotProduct(Short2 a, Short2 b) {
+        return (short)((b.x * a.x) + (b.y * a.y));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Short2 a, short factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+    }
+
+    /** @hide
+     * set vector value by Short2
+     *
+     * @param a
+     */
+    public void set(Short2 a) {
+        this.x = a.x;
+        this.y = a.y;
+    }
+
+    /** @hide
+     * set the vector field value by Short
+     *
+     * @param a
+     * @param b
+     */
+    public void setValues(short a, short b) {
+        this.x = a;
+        this.y = b;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public short elementSum() {
+        return (short)(x + y);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public short get(int i) {
+        switch (i) {
+        case 0:
+            return (short)(x);
+        case 1:
+            return (short)(y);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, short value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, short value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to short array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(short[] data, int offset) {
+        data[offset] = (short)(x);
+        data[offset + 1] = (short)(y);
+    }
+}
diff --git a/android/renderscript/Short3.java b/android/renderscript/Short3.java
new file mode 100644
index 0000000..3d70f07
--- /dev/null
+++ b/android/renderscript/Short3.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic short type.
+ * Provides three short fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Short3 {
+    public short x;
+    public short y;
+    public short z;
+
+    public Short3() {
+    }
+
+    /** @hide */
+    public Short3(short i) {
+        this.x = this.y = this.z = i;
+    }
+
+    public Short3(short x, short y, short z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+
+    /** @hide */
+    public Short3(Short3 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Short3 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 add(Short3 a, Short3 b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x + b.x);
+        result.y = (short)(a.y + b.y);
+        result.z = (short)(a.z + b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(short value) {
+        x += value;
+        y += value;
+        z += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 add(Short3 a, short b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x + b);
+        result.y = (short)(a.y + b);
+        result.z = (short)(a.z + b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Short3 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 sub(Short3 a, Short3 b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x - b.x);
+        result.y = (short)(a.y - b.y);
+        result.z = (short)(a.z - b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(short value) {
+        x -= value;
+        y -= value;
+        z -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 sub(Short3 a, short b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x - b);
+        result.y = (short)(a.y - b);
+        result.z = (short)(a.z - b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Short3 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 mul(Short3 a, Short3 b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x * b.x);
+        result.y = (short)(a.y * b.y);
+        result.z = (short)(a.z * b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(short value) {
+        x *= value;
+        y *= value;
+        z *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 mul(Short3 a, short b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x * b);
+        result.y = (short)(a.y * b);
+        result.z = (short)(a.z * b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Short3 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 div(Short3 a, Short3 b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x / b.x);
+        result.y = (short)(a.y / b.y);
+        result.z = (short)(a.z / b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(short value) {
+        x /= value;
+        y /= value;
+        z /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 div(Short3 a, short b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x / b);
+        result.y = (short)(a.y / b);
+        result.z = (short)(a.z / b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Short3 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+        this.z %= a.z;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 mod(Short3 a, Short3 b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x % b.x);
+        result.y = (short)(a.y % b.y);
+        result.z = (short)(a.z % b.z);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(short value) {
+        x %= value;
+        y %= value;
+        z %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short3 mod(Short3 a, short b) {
+        Short3 result = new Short3();
+        result.x = (short)(a.x % b);
+        result.y = (short)(a.y % b);
+        result.z = (short)(a.z % b);
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public short length() {
+        return 3;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = (short)(-x);
+        this.y = (short)(-y);
+        this.z = (short)(-z);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public short dotProduct(Short3 a) {
+        return (short)((x * a.x) + (y * a.y) + (z * a.z));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static short dotProduct(Short3 a, Short3 b) {
+        return (short)((b.x * a.x) + (b.y * a.y) + (b.z * a.z));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Short3 a, short factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+    }
+
+    /** @hide
+     * set vector value by Short3
+     *
+     * @param a
+     */
+    public void set(Short3 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+    }
+
+    /** @hide
+     * set the vector field value by Short
+     *
+     * @param a
+     * @param b
+     * @param c
+     */
+    public void setValues(short a, short b, short c) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public short elementSum() {
+        return (short)(x + y + z);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public short get(int i) {
+        switch (i) {
+        case 0:
+            return (short)(x);
+        case 1:
+            return (short)(y);
+        case 2:
+            return (short)(z);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, short value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, short value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to short array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(short[] data, int offset) {
+        data[offset] = (short)(x);
+        data[offset + 1] = (short)(y);
+        data[offset + 2] = (short)(z);
+    }
+}
diff --git a/android/renderscript/Short4.java b/android/renderscript/Short4.java
new file mode 100644
index 0000000..c90d648
--- /dev/null
+++ b/android/renderscript/Short4.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Vector version of the basic short type.
+ * Provides four short fields packed.
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ */
+@Deprecated
+public class Short4 {
+    public short x;
+    public short y;
+    public short z;
+    public short w;
+
+    public Short4() {
+    }
+
+    /** @hide */
+    public Short4(short i) {
+        this.x = this.y = this.z = this.w = i;
+    }
+
+    public Short4(short x, short y, short z, short w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /** @hide */
+    public Short4(Short4 source) {
+        this.x = source.x;
+        this.y = source.y;
+        this.z = source.z;
+        this.w = source.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     */
+    public void add(Short4 a) {
+        this.x += a.x;
+        this.y += a.y;
+        this.z += a.z;
+        this.w += a.w;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 add(Short4 a, Short4 b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x + b.x);
+        result.y = (short)(a.y + b.y);
+        result.z = (short)(a.z + b.z);
+        result.w = (short)(a.w + b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param value
+     */
+    public void add(short value) {
+        x += value;
+        y += value;
+        z += value;
+        w += value;
+    }
+
+    /** @hide
+     * Vector add
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 add(Short4 a, short b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x + b);
+        result.y = (short)(a.y + b);
+        result.z = (short)(a.z + b);
+        result.w = (short)(a.w + b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     */
+    public void sub(Short4 a) {
+        this.x -= a.x;
+        this.y -= a.y;
+        this.z -= a.z;
+        this.w -= a.w;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 sub(Short4 a, Short4 b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x - b.x);
+        result.y = (short)(a.y - b.y);
+        result.z = (short)(a.z - b.z);
+        result.w = (short)(a.w - b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param value
+     */
+    public void sub(short value) {
+        x -= value;
+        y -= value;
+        z -= value;
+        w -= value;
+    }
+
+    /** @hide
+     * Vector subtraction
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 sub(Short4 a, short b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x - b);
+        result.y = (short)(a.y - b);
+        result.z = (short)(a.z - b);
+        result.w = (short)(a.w - b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     */
+    public void mul(Short4 a) {
+        this.x *= a.x;
+        this.y *= a.y;
+        this.z *= a.z;
+        this.w *= a.w;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 mul(Short4 a, Short4 b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x * b.x);
+        result.y = (short)(a.y * b.y);
+        result.z = (short)(a.z * b.z);
+        result.w = (short)(a.w * b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param value
+     */
+    public void mul(short value) {
+        x *= value;
+        y *= value;
+        z *= value;
+        w *= value;
+    }
+
+    /** @hide
+     * Vector multiplication
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 mul(Short4 a, short b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x * b);
+        result.y = (short)(a.y * b);
+        result.z = (short)(a.z * b);
+        result.w = (short)(a.w * b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     */
+    public void div(Short4 a) {
+        this.x /= a.x;
+        this.y /= a.y;
+        this.z /= a.z;
+        this.w /= a.w;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 div(Short4 a, Short4 b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x / b.x);
+        result.y = (short)(a.y / b.y);
+        result.z = (short)(a.z / b.z);
+        result.w = (short)(a.w / b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param value
+     */
+    public void div(short value) {
+        x /= value;
+        y /= value;
+        z /= value;
+        w /= value;
+    }
+
+    /** @hide
+     * Vector division
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 div(Short4 a, short b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x / b);
+        result.y = (short)(a.y / b);
+        result.z = (short)(a.z / b);
+        result.w = (short)(a.w / b);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     */
+    public void mod(Short4 a) {
+        this.x %= a.x;
+        this.y %= a.y;
+        this.z %= a.z;
+        this.w %= a.w;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 mod(Short4 a, Short4 b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x % b.x);
+        result.y = (short)(a.y % b.y);
+        result.z = (short)(a.z % b.z);
+        result.w = (short)(a.w % b.w);
+
+        return result;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param value
+     */
+    public void mod(short value) {
+        x %= value;
+        y %= value;
+        z %= value;
+        w %= value;
+    }
+
+    /** @hide
+     * Vector Modulo
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static Short4 mod(Short4 a, short b) {
+        Short4 result = new Short4();
+        result.x = (short)(a.x % b);
+        result.y = (short)(a.y % b);
+        result.z = (short)(a.z % b);
+        result.w = (short)(a.w % b);
+
+        return result;
+    }
+
+    /** @hide
+     * get vector length
+     *
+     * @return
+     */
+    public short length() {
+        return 4;
+    }
+
+    /** @hide
+     * set vector negate
+     */
+    public void negate() {
+        this.x = (short)(-x);
+        this.y = (short)(-y);
+        this.z = (short)(-z);
+        this.w = (short)(-w);
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @return
+     */
+    public short dotProduct(Short4 a) {
+        return (short)((x * a.x) + (y * a.y) + (z * a.z) + (w * a.w));
+    }
+
+    /** @hide
+     * Vector dot Product
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    public static short dotProduct(Short4 a, Short4 b) {
+        return (short)((b.x * a.x) + (b.y * a.y) + (b.z * a.z) + (b.w * a.w));
+    }
+
+    /** @hide
+     * Vector add Multiple
+     *
+     * @param a
+     * @param factor
+     */
+    public void addMultiple(Short4 a, short factor) {
+        x += a.x * factor;
+        y += a.y * factor;
+        z += a.z * factor;
+        w += a.w * factor;
+    }
+
+    /** @hide
+     * set vector value by Short4
+     *
+     * @param a
+     */
+    public void set(Short4 a) {
+        this.x = a.x;
+        this.y = a.y;
+        this.z = a.z;
+        this.w = a.w;
+    }
+
+    /** @hide
+     * set the vector field value by Short
+     *
+     * @param a
+     * @param b
+     * @param c
+     * @param d
+     */
+    public void setValues(short a, short b, short c, short d) {
+        this.x = a;
+        this.y = b;
+        this.z = c;
+        this.w = d;
+    }
+
+    /** @hide
+     * return the element sum of vector
+     *
+     * @return
+     */
+    public short elementSum() {
+        return (short)(x + y + z + w);
+    }
+
+    /** @hide
+     * get the vector field value by index
+     *
+     * @param i
+     * @return
+     */
+    public short get(int i) {
+        switch (i) {
+        case 0:
+            return (short)(x);
+        case 1:
+            return (short)(y);
+        case 2:
+            return (short)(z);
+        case 3:
+            return (short)(w);
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * set the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void setAt(int i, short value) {
+        switch (i) {
+        case 0:
+            x = value;
+            return;
+        case 1:
+            y = value;
+            return;
+        case 2:
+            z = value;
+            return;
+        case 3:
+            w = value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * add the vector field value by index
+     *
+     * @param i
+     * @param value
+     */
+    public void addAt(int i, short value) {
+        switch (i) {
+        case 0:
+            x += value;
+            return;
+        case 1:
+            y += value;
+            return;
+        case 2:
+            z += value;
+            return;
+        case 3:
+            w += value;
+            return;
+        default:
+            throw new IndexOutOfBoundsException("Index: i");
+        }
+    }
+
+    /** @hide
+     * copy the vector to short array
+     *
+     * @param data
+     * @param offset
+     */
+    public void copyTo(short[] data, int offset) {
+        data[offset] = (short)(x);
+        data[offset + 1] = (short)(y);
+        data[offset + 2] = (short)(z);
+        data[offset + 3] = (short)(w);
+    }
+}
diff --git a/android/renderscript/Type.java b/android/renderscript/Type.java
new file mode 100644
index 0000000..021fd06
--- /dev/null
+++ b/android/renderscript/Type.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * <p>A Type describes the {@link android.renderscript.Element} and dimensions used for an {@link
+ * android.renderscript.Allocation} or a parallel operation. Types are created through {@link
+ * android.renderscript.Type.Builder}.</p>
+ *
+ * <p>A Type always includes an {@link android.renderscript.Element} and an X
+ * dimension. A Type may be multidimensional, up to three dimensions. A nonzero
+ * value in the Y or Z dimensions indicates that the dimension is present. Note
+ * that a Type with only a given X dimension and a Type with the same X
+ * dimension but Y = 1 are not equivalent.</p>
+ *
+ * <p>A Type also supports inclusion of level of detail (LOD) or cube map
+ * faces. LOD and cube map faces are booleans to indicate present or not
+ * present. </p>
+ *
+ * <p>A Type also supports YUV format information to support an
+ * {@link android.renderscript.Allocation} in a YUV format. The YUV formats
+ * supported are {@link android.graphics.ImageFormat#YV12},
+ * {@link android.graphics.ImageFormat#NV21}, and
+ * {@link android.graphics.ImageFormat#YUV_420_888}</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ *
+ * @deprecated Renderscript has been deprecated in API level 31. Please refer to the <a
+ * href="https://developer.android.com/guide/topics/renderscript/migration-guide">migration
+ * guide</a> for the proposed alternatives.
+ **/
+@Deprecated
+public class Type extends BaseObj {
+    int mDimX;
+    int mDimY;
+    int mDimZ;
+    boolean mDimMipmaps;
+    boolean mDimFaces;
+    int mDimYuv;
+    int mElementCount;
+    Element mElement;
+    int mArrays[];
+
+    static final int mMaxArrays = 4;
+
+    public enum CubemapFace {
+        POSITIVE_X (0),
+        NEGATIVE_X (1),
+        POSITIVE_Y (2),
+        NEGATIVE_Y (3),
+        POSITIVE_Z (4),
+        NEGATIVE_Z (5),
+        @Deprecated
+        POSITVE_X (0),
+        @Deprecated
+        POSITVE_Y (2),
+        @Deprecated
+        POSITVE_Z (4);
+
+        int mID;
+        CubemapFace(int id) {
+            mID = id;
+        }
+    }
+
+    /**
+     * Return the element associated with this Type.
+     *
+     * @return Element
+     */
+    public Element getElement() {
+        return mElement;
+    }
+
+    /**
+     * Return the value of the X dimension.
+     *
+     * @return int
+     */
+    public int getX() {
+        return mDimX;
+    }
+
+    /**
+     * Return the value of the Y dimension or 0 for a 1D allocation.
+     *
+     * @return int
+     */
+    public int getY() {
+        return mDimY;
+    }
+
+    /**
+     * Return the value of the Z dimension or 0 for a 1D or 2D allocation.
+     *
+     * @return int
+     */
+    public int getZ() {
+        return mDimZ;
+    }
+
+    /**
+     * Get the YUV format
+     *
+     *
+     * @return int
+     */
+    public int getYuv() {
+        return mDimYuv;
+    }
+
+    /**
+     * Return if the Type has a mipmap chain.
+     *
+     * @return boolean
+     */
+    public boolean hasMipmaps() {
+        return mDimMipmaps;
+    }
+
+    /**
+     * Return if the Type is a cube map.
+     *
+     * @return boolean
+     */
+    public boolean hasFaces() {
+        return mDimFaces;
+    }
+
+    /**
+     * Return the total number of accessable cells in the Type.
+     *
+     * @return int
+     */
+    public int getCount() {
+        return mElementCount;
+    }
+
+    /**
+     * @hide
+      * Return the dimension of the specified array.
+      *
+      * @param arrayNum  The array dimension to query
+      * @return int
+      */
+    public int getArray(int arrayNum) {
+        if ((arrayNum < 0) || (arrayNum >= mMaxArrays)) {
+            throw new RSIllegalArgumentException("Array dimension out of range.");
+        }
+
+        if (mArrays == null || arrayNum >= mArrays.length) {
+            // Dimension in range but no array for that dimension allocated
+            return 0;
+        }
+
+        return mArrays[arrayNum];
+    }
+
+    /**
+     * @hide
+      * Return the number of array dimensions.
+      *
+      * @return int
+      */
+    public int getArrayCount() {
+        if (mArrays != null) return mArrays.length;
+        return 0;
+    }
+
+    void calcElementCount() {
+        boolean hasLod = hasMipmaps();
+        int x = getX();
+        int y = getY();
+        int z = getZ();
+        int faces = 1;
+        if (hasFaces()) {
+            faces = 6;
+        }
+        if (x == 0) {
+            x = 1;
+        }
+        if (y == 0) {
+            y = 1;
+        }
+        if (z == 0) {
+            z = 1;
+        }
+
+        int count = x * y * z * faces;
+
+        while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
+            if(x > 1) {
+                x >>= 1;
+            }
+            if(y > 1) {
+                y >>= 1;
+            }
+            if(z > 1) {
+                z >>= 1;
+            }
+
+            count += x * y * z * faces;
+        }
+
+        if (mArrays != null) {
+            for (int ct = 0; ct < mArrays.length; ct++) {
+                count *= mArrays[ct];
+            }
+        }
+
+        mElementCount = count;
+    }
+
+
+    Type(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    @Override
+    void updateFromNative() {
+        // We have 6 integer/long to obtain mDimX; mDimY; mDimZ;
+        // mDimLOD; mDimFaces; mElement;
+        long[] dataBuffer = new long[6];
+        mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
+
+        mDimX = (int)dataBuffer[0];
+        mDimY = (int)dataBuffer[1];
+        mDimZ = (int)dataBuffer[2];
+        mDimMipmaps = dataBuffer[3] == 1 ? true : false;
+        mDimFaces = dataBuffer[4] == 1 ? true : false;
+
+        long elementID = dataBuffer[5];
+        if(elementID != 0) {
+            mElement = new Element(elementID, mRS);
+            mElement.updateFromNative();
+        }
+        calcElementCount();
+    }
+
+    /**
+     * Utility function for creating basic 1D types. The type is
+     * created without mipmaps enabled.
+     *
+     * @param rs The RenderScript context
+     * @param e The Element for the Type
+     * @param dimX The X dimension, must be > 0
+     *
+     * @return Type
+     */
+    static public Type createX(RenderScript rs, Element e, int dimX) {
+        if (dimX < 1) {
+            throw new RSInvalidStateException("Dimension must be >= 1.");
+        }
+
+        long id = rs.nTypeCreate(e.getID(rs), dimX, 0, 0, false, false, 0);
+        Type t = new Type(id, rs);
+        t.mElement = e;
+        t.mDimX = dimX;
+        t.calcElementCount();
+        return t;
+    }
+
+    /**
+     * Utility function for creating basic 2D types. The type is
+     * created without mipmaps or cubemaps.
+     *
+     * @param rs The RenderScript context
+     * @param e The Element for the Type
+     * @param dimX The X dimension, must be > 0
+     * @param dimY The Y dimension, must be > 0
+     *
+     * @return Type
+     */
+    static public Type createXY(RenderScript rs, Element e, int dimX, int dimY) {
+        if ((dimX < 1) || (dimY < 1)) {
+            throw new RSInvalidStateException("Dimension must be >= 1.");
+        }
+
+        long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, 0, false, false, 0);
+        Type t = new Type(id, rs);
+        t.mElement = e;
+        t.mDimX = dimX;
+        t.mDimY = dimY;
+        t.calcElementCount();
+        return t;
+    }
+
+    /**
+     * Utility function for creating basic 3D types. The type is
+     * created without mipmaps.
+     *
+     * @param rs The RenderScript context
+     * @param e The Element for the Type
+     * @param dimX The X dimension, must be > 0
+     * @param dimY The Y dimension, must be > 0
+     * @param dimZ The Z dimension, must be > 0
+     *
+     * @return Type
+     */
+    static public Type createXYZ(RenderScript rs, Element e, int dimX, int dimY, int dimZ) {
+        if ((dimX < 1) || (dimY < 1) || (dimZ < 1)) {
+            throw new RSInvalidStateException("Dimension must be >= 1.");
+        }
+
+        long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, dimZ, false, false, 0);
+        Type t = new Type(id, rs);
+        t.mElement = e;
+        t.mDimX = dimX;
+        t.mDimY = dimY;
+        t.mDimZ = dimZ;
+        t.calcElementCount();
+        return t;
+    }
+
+    /**
+     * Builder class for Type.
+     *
+     */
+    public static class Builder {
+        RenderScript mRS;
+        int mDimX = 1;
+        int mDimY;
+        int mDimZ;
+        boolean mDimMipmaps;
+        boolean mDimFaces;
+        int mYuv;
+        int[] mArray = new int[mMaxArrays];
+
+        Element mElement;
+
+        /**
+         * Create a new builder object.
+         *
+         * @param rs
+         * @param e The element for the type to be created.
+         */
+        public Builder(RenderScript rs, Element e) {
+            e.checkValid();
+            mRS = rs;
+            mElement = e;
+        }
+
+        /**
+         * Add a dimension to the Type.
+         *
+         *
+         * @param value
+         */
+        public Builder setX(int value) {
+            if(value < 1) {
+                throw new RSIllegalArgumentException("Values of less than 1 for Dimension X are not valid.");
+            }
+            mDimX = value;
+            return this;
+        }
+
+        public Builder setY(int value) {
+            if(value < 1) {
+                throw new RSIllegalArgumentException("Values of less than 1 for Dimension Y are not valid.");
+            }
+            mDimY = value;
+            return this;
+        }
+
+        public Builder setZ(int value) {
+            if(value < 1) {
+                throw new RSIllegalArgumentException("Values of less than 1 for Dimension Z are not valid.");
+            }
+            mDimZ = value;
+            return this;
+        }
+
+        /**
+         * @hide
+         * Adds an array dimension to the builder
+         *
+         * @param dim
+         * @param value
+         *
+         * @return Builder
+         */
+        public Builder setArray(int dim, int value) {
+            if(dim < 0 || dim >= mMaxArrays) {
+                throw new RSIllegalArgumentException("Array dimension out of range.");
+            }
+            mArray[dim] = value;
+            return this;
+        }
+
+        public Builder setMipmaps(boolean value) {
+            mDimMipmaps = value;
+            return this;
+        }
+
+        public Builder setFaces(boolean value) {
+            mDimFaces = value;
+            return this;
+        }
+
+        /**
+         * Set the YUV layout for a Type.
+         *
+         * @param yuvFormat {@link android.graphics.ImageFormat#YV12}, {@link android.graphics.ImageFormat#NV21}, or
+         * {@link android.graphics.ImageFormat#YUV_420_888}.
+         */
+        public Builder setYuvFormat(int yuvFormat) {
+            switch (yuvFormat) {
+            case android.graphics.ImageFormat.NV21:
+            case android.graphics.ImageFormat.YV12:
+            case android.graphics.ImageFormat.YUV_420_888:
+                break;
+
+            default:
+                throw new RSIllegalArgumentException(
+                    "Only ImageFormat.NV21, .YV12, and .YUV_420_888 are supported..");
+            }
+
+            mYuv = yuvFormat;
+            return this;
+        }
+
+
+        /**
+         * Validate structure and create a new Type.
+         *
+         * @return Type
+         */
+        public Type create() {
+            if (mDimZ > 0) {
+                if ((mDimX < 1) || (mDimY < 1)) {
+                    throw new RSInvalidStateException("Both X and Y dimension required when Z is present.");
+                }
+                if (mDimFaces) {
+                    throw new RSInvalidStateException("Cube maps not supported with 3D types.");
+                }
+            }
+            if (mDimY > 0) {
+                if (mDimX < 1) {
+                    throw new RSInvalidStateException("X dimension required when Y is present.");
+                }
+            }
+            if (mDimFaces) {
+                if (mDimY < 1) {
+                    throw new RSInvalidStateException("Cube maps require 2D Types.");
+                }
+            }
+
+            if (mYuv != 0) {
+                if ((mDimZ != 0) || mDimFaces || mDimMipmaps) {
+                    throw new RSInvalidStateException("YUV only supports basic 2D.");
+                }
+            }
+
+            int[] arrays = null;
+            for (int ct = mMaxArrays - 1; ct >= 0; ct--) {
+                if (mArray[ct] != 0 && arrays == null) {
+                    arrays = new int[ct];
+                }
+                if ((mArray[ct] == 0) && (arrays != null)) {
+                    throw new RSInvalidStateException("Array dimensions must be contigous from 0.");
+                }
+            }
+
+            long id = mRS.nTypeCreate(mElement.getID(mRS),
+                                     mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces, mYuv);
+            Type t = new Type(id, mRS);
+            t.mElement = mElement;
+            t.mDimX = mDimX;
+            t.mDimY = mDimY;
+            t.mDimZ = mDimZ;
+            t.mDimMipmaps = mDimMipmaps;
+            t.mDimFaces = mDimFaces;
+            t.mDimYuv = mYuv;
+            t.mArrays = arrays;
+
+            t.calcElementCount();
+            return t;
+        }
+    }
+
+}