Move compute tests from frameworks/base to frameworks/rs

Change-Id: I844c9f5e58f500164fec419569c68c7f854c5571
diff --git a/java/tests/Balls/Android.mk b/java/tests/Balls/Android.mk
new file mode 100644
index 0000000..77281ce
--- /dev/null
+++ b/java/tests/Balls/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsBalls
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/Balls/AndroidManifest.xml b/java/tests/Balls/AndroidManifest.xml
new file mode 100644
index 0000000..80e6b39
--- /dev/null
+++ b/java/tests/Balls/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.balls">
+    <uses-sdk android:minSdkVersion="14" />
+    <application 
+        android:label="RsBalls"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="Balls"
+                  android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/Balls/_index.html b/java/tests/Balls/_index.html
new file mode 100644
index 0000000..8760485
--- /dev/null
+++ b/java/tests/Balls/_index.html
@@ -0,0 +1 @@
+<p>A brute force physics simulation that renders many balls onto the screen and moves them according to user touch and gravity.</p>
\ No newline at end of file
diff --git a/java/tests/Balls/res/drawable/flares.png b/java/tests/Balls/res/drawable/flares.png
new file mode 100644
index 0000000..3a5c970
--- /dev/null
+++ b/java/tests/Balls/res/drawable/flares.png
Binary files differ
diff --git a/java/tests/Balls/res/drawable/test_pattern.png b/java/tests/Balls/res/drawable/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/java/tests/Balls/res/drawable/test_pattern.png
Binary files differ
diff --git a/java/tests/Balls/src/com/example/android/rs/balls/Balls.java b/java/tests/Balls/src/com/example/android/rs/balls/Balls.java
new file mode 100644
index 0000000..2c6558e
--- /dev/null
+++ b/java/tests/Balls/src/com/example/android/rs/balls/Balls.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.example.android.rs.balls;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+public class Balls extends Activity implements SensorEventListener {
+    //EventListener mListener = new EventListener();
+
+    private static final String LOG_TAG = "libRS_jni";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private BallsView mView;
+    private SensorManager mSensorManager;
+
+    // get the current looper (from your Activity UI thread for instance
+
+
+    public void onSensorChanged(SensorEvent event) {
+        //android.util.Log.d("rs", "sensor: " + event.sensor + ", x: " + event.values[0] + ", y: " + event.values[1] + ", z: " + event.values[2]);
+        synchronized (this) {
+            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+                if(mView != null) {
+                    mView.setAccel(event.values[0], event.values[1], event.values[2]);
+                }
+            }
+        }
+    }
+
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new BallsView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        mSensorManager.registerListener(this,
+                                        mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+                                        SensorManager.SENSOR_DELAY_FASTEST);
+
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.pause();
+        onStop();
+    }
+
+    @Override
+    protected void onStop() {
+        mSensorManager.unregisterListener(this);
+        super.onStop();
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
+
diff --git a/java/tests/Balls/src/com/example/android/rs/balls/BallsRS.java b/java/tests/Balls/src/com/example/android/rs/balls/BallsRS.java
new file mode 100644
index 0000000..d9d182c
--- /dev/null
+++ b/java/tests/Balls/src/com/example/android/rs/balls/BallsRS.java
@@ -0,0 +1,151 @@
+/*
+ * 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 com.example.android.rs.balls;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+
+public class BallsRS {
+    public static final int PART_COUNT = 4000;
+
+    public BallsRS() {
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+    private ScriptC_balls mScript;
+    private ScriptC_ball_physics mPhysicsScript;
+    private ProgramFragment mPFPoints;
+    private ScriptField_Point mPoints;
+    private ScriptField_VpConsts mVpConsts;
+    private ScriptField_BallGrid mGrid;
+    private ScriptField_Ball mBalls;
+    private Allocation mGridCache;
+
+    void updateProjectionMatrices() {
+        mVpConsts = new ScriptField_VpConsts(mRS, 1,
+                                             Allocation.USAGE_SCRIPT |
+                                             Allocation.USAGE_GRAPHICS_CONSTANTS);
+        ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+        Matrix4f mvp = new Matrix4f();
+        mvp.loadOrtho(0, mRS.getWidth(), mRS.getHeight(), 0, -1, 1);
+        i.MVP = mvp;
+        mVpConsts.set(i, 0, true);
+    }
+
+    private void createProgramVertex() {
+        updateProjectionMatrices();
+
+        ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
+        String t =  "varying vec4 varColor;\n" +
+                    "void main() {\n" +
+                    "  vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
+                    "  pos.xy = ATTRIB_position;\n" +
+                    "  gl_Position = UNI_MVP * pos;\n" +
+                    "  varColor = ATTRIB_color;\n" +
+                    "  gl_PointSize = 12.0;\n" +
+                    "}\n";
+        sb.setShader(t);
+        sb.addConstant(mVpConsts.getType());
+        sb.addInput(mPoints.getElement());
+        ProgramVertex pvs = sb.create();
+        pvs.bindConstants(mVpConsts.getAllocation(), 0);
+        mRS.bindProgramVertex(pvs);
+    }
+
+    private Allocation loadTexture(int id) {
+        final Allocation allocation =
+            Allocation.createFromBitmapResource(mRS, mRes,
+                id, Allocation.MipmapControl.MIPMAP_NONE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+        return allocation;
+    }
+
+    ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
+        ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+        builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE);
+        builder.setDitherEnabled(false);
+        builder.setDepthMaskEnabled(false);
+        return builder.create();
+    }
+
+    private void createPF(int width, int height) {
+        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(mRS);
+        pfb.setPointSpriteTexCoordinateReplacement(true);
+        pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
+                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+        pfb.setVaryingColor(true);
+        mPFPoints = pfb.create();
+    }
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+
+        createPF(width, height);
+
+        mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0);
+
+        mPoints = new ScriptField_Point(mRS, PART_COUNT, Allocation.USAGE_SCRIPT);
+
+        Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
+        smb.addVertexAllocation(mPoints.getAllocation());
+        smb.addIndexSetType(Mesh.Primitive.POINT);
+        Mesh smP = smb.create();
+
+        mGrid = ScriptField_BallGrid.create2D(mRS, (width + 99) / 100, (height + 99) / 100);
+        mGridCache = Allocation.createSized(mRS, Element.F32_2(mRS), PART_COUNT);
+        mBalls = new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT);
+
+        mPhysicsScript = new ScriptC_ball_physics(mRS);
+        mPhysicsScript.set_gGridCache(mGridCache);
+        mPhysicsScript.set_gBalls(mBalls.getAllocation());
+
+        mScript = new ScriptC_balls(mRS);
+        mScript.set_partMesh(smP);
+        mScript.set_physics_script(mPhysicsScript);
+        mScript.bind_point(mPoints);
+        mScript.bind_balls(mBalls);
+        mScript.set_gGrid(mGrid.getAllocation());
+        mScript.bind_gGridCache(mGridCache);
+
+        mScript.set_gPFPoints(mPFPoints);
+        createProgramVertex();
+
+        mRS.bindProgramStore(BLEND_ADD_DEPTH_NONE(mRS));
+
+        mPhysicsScript.set_gMinPos(new Float2(5, 5));
+        mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));
+        mPhysicsScript.set_gGrid(mGrid.getAllocation());
+
+        mScript.invoke_initParts(width, height);
+
+        mRS.bindRootScript(mScript);
+    }
+
+    public void newTouchPosition(float x, float y, float pressure, int id) {
+        mPhysicsScript.invoke_touch(x, y, pressure * mRS.getWidth() / 1280, id);
+    }
+
+    public void setAccel(float x, float y) {
+        mPhysicsScript.set_gGravityVector(new Float2(x, y));
+    }
+
+}
diff --git a/java/tests/Balls/src/com/example/android/rs/balls/BallsView.java b/java/tests/Balls/src/com/example/android/rs/balls/BallsView.java
new file mode 100644
index 0000000..041782d
--- /dev/null
+++ b/java/tests/Balls/src/com/example/android/rs/balls/BallsView.java
@@ -0,0 +1,116 @@
+/*
+ * 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 com.example.android.rs.balls;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class BallsView extends RSSurfaceView {
+
+    public BallsView(Context context) {
+        super(context);
+        //setFocusable(true);
+    }
+
+    private RenderScriptGL mRS;
+    private BallsRS mRender;
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRS = createRenderScriptGL(sc);
+            mRS.setSurface(holder, w, h);
+            mRender = new BallsRS();
+            mRender.init(mRS, getResources(), w, h);
+        }
+        mRender.updateProjectionMatrices();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if(mRS != null) {
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev)
+    {
+        int act = ev.getActionMasked();
+        if (act == ev.ACTION_UP) {
+            mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
+            return false;
+        } else if (act == MotionEvent.ACTION_POINTER_UP) {
+            // only one pointer going up, we can get the index like this
+            int pointerIndex = ev.getActionIndex();
+            int pointerId = ev.getPointerId(pointerIndex);
+            mRender.newTouchPosition(0, 0, 0, pointerId);
+            return false;
+        }
+        int count = ev.getHistorySize();
+        int pcount = ev.getPointerCount();
+
+        for (int p=0; p < pcount; p++) {
+            int id = ev.getPointerId(p);
+            mRender.newTouchPosition(ev.getX(p),
+                                     ev.getY(p),
+                                     ev.getPressure(p),
+                                     id);
+
+            for (int i=0; i < count; i++) {
+                mRender.newTouchPosition(ev.getHistoricalX(p, i),
+                                         ev.getHistoricalY(p, i),
+                                         ev.getHistoricalPressure(p, i),
+                                         id);
+            }
+        }
+        return true;
+    }
+
+    void setAccel(float x, float y, float z) {
+        if ((mRender == null) || (mRS == null)) {
+            return;
+        }
+        mRender.setAccel(x, -y);
+    }
+
+}
+
+
diff --git a/java/tests/Balls/src/com/example/android/rs/balls/ball_physics.rs b/java/tests/Balls/src/com/example/android/rs/balls/ball_physics.rs
new file mode 100644
index 0000000..5b5d2e0
--- /dev/null
+++ b/java/tests/Balls/src/com/example/android/rs/balls/ball_physics.rs
@@ -0,0 +1,155 @@
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.balls)
+
+#include "balls.rsh"
+
+float2 gGravityVector = {0.f, 9.8f};
+
+float2 gMinPos = {0.f, 0.f};
+float2 gMaxPos = {1280.f, 700.f};
+
+static float2 touchPos[10];
+static float touchPressure[10];
+static const float gDT = 1.f / 30.f;
+
+rs_allocation gGrid;
+rs_allocation gGridCache;
+rs_allocation gBalls;
+
+float gScale = 1.f;
+
+void touch(float x, float y, float pressure, int id) {
+    if (id >= 10) {
+        return;
+    }
+
+    touchPos[id].x = x;
+    touchPos[id].y = y;
+    touchPressure[id] = pressure;
+}
+
+void root(Ball_t *ball, uint32_t x) {
+    float2 fv = 0;
+    float pressure = 0;
+    float2 pos = ball->position;
+    int2 gridPos[9];
+
+    gridPos[0] = convert_int2((ball->position / 100.f) /*- 0.4999f*/);
+    gridPos[1] = (int2){gridPos[0].x - 1, gridPos[0].y - 1};
+    gridPos[2] = (int2){gridPos[0].x + 0, gridPos[0].y - 1};
+    gridPos[3] = (int2){gridPos[0].x + 1, gridPos[0].y - 1};
+    gridPos[4] = (int2){gridPos[0].x - 1, gridPos[0].y};
+    gridPos[5] = (int2){gridPos[0].x + 1, gridPos[0].y};
+    gridPos[6] = (int2){gridPos[0].x - 1, gridPos[0].y + 1};
+    gridPos[7] = (int2){gridPos[0].x + 0, gridPos[0].y + 1};
+    gridPos[8] = (int2){gridPos[0].x + 1, gridPos[0].y + 1};
+
+    for (int gct=0; gct < 9; gct++) {
+        if ((gridPos[gct].x >= rsAllocationGetDimX(gGrid)) ||
+            (gridPos[gct].x < 0) ||
+            (gridPos[gct].y >= rsAllocationGetDimY(gGrid)) ||
+            (gridPos[gct].y < 0)) {
+            continue;
+        }
+        //rsDebug("grid ", gridPos[gct]);
+        const BallGrid_t *bg = (const BallGrid_t *)rsGetElementAt(gGrid, gridPos[gct].x, gridPos[gct].y);
+
+        for (int cidx = 0; cidx < bg->count; cidx++) {
+            float2 bcptr = rsGetElementAt_float2(gGridCache, bg->cacheIdx + cidx);
+            float2 vec = bcptr - pos;
+            float2 vec2 = vec * vec;
+            float len2 = vec2.x + vec2.y;
+
+            if ((len2 < 10000.f) && (len2 > 0.f)) {
+                float t = native_powr(len2, 1.5f) + 16.0f;
+                float2 pfv = (vec / t) * 16000.f;
+                pressure += length(pfv);
+                fv -= pfv;
+            }
+        }
+    }
+
+    //fv /= ball->size * ball->size * ball->size;
+    fv -= gGravityVector * 4.f * gScale;
+    fv *= gDT;
+
+    for (int i=0; i < 10; i++) {
+        if (touchPressure[i] > 0.1f) {
+            float2 vec = touchPos[i] - ball->position;
+            float2 vec2 = vec * vec;
+            float len2 = max(2.f, vec2.x + vec2.y);
+            float2 pfv = (vec / len2) * touchPressure[i] * 500.f * gScale;
+            pressure += length(pfv);
+            fv -= pfv;
+        }
+    }
+
+    ball->delta = (ball->delta * (1.f - 0.008f)) + fv;
+    ball->position = ball->position + (ball->delta * gDT);
+
+    const float wallForce = 400.f * gScale;
+    if (ball->position.x > (gMaxPos.x - 20.f)) {
+        float d = gMaxPos.x - ball->position.x;
+        if (d < 0.f) {
+            if (ball->delta.x > 0) {
+                ball->delta.x *= -0.7f;
+            }
+            ball->position.x = gMaxPos.x - 1.f;
+        } else {
+            ball->delta.x -= min(wallForce / (d * d), 10.f);
+        }
+    }
+
+    if (ball->position.x < (gMinPos.x + 20.f)) {
+        float d = ball->position.x - gMinPos.x;
+        if (d < 0.f) {
+            if (ball->delta.x < 0) {
+                ball->delta.x *= -0.7f;
+            }
+            ball->position.x = gMinPos.x + 1.f;
+        } else {
+            ball->delta.x += min(wallForce / (d * d), 10.f);
+        }
+    }
+
+    if (ball->position.y > (gMaxPos.y - 20.f)) {
+        float d = gMaxPos.y - ball->position.y;
+        if (d < 0.f) {
+            if (ball->delta.y > 0) {
+                ball->delta.y *= -0.7f;
+            }
+            ball->position.y = gMaxPos.y - 1.f;
+        } else {
+            ball->delta.y -= min(wallForce / (d * d), 10.f);
+        }
+    }
+
+    if (ball->position.y < (gMinPos.y + 20.f)) {
+        float d = ball->position.y - gMinPos.y;
+        if (d < 0.f) {
+            if (ball->delta.y < 0) {
+                ball->delta.y *= -0.7f;
+            }
+            ball->position.y = gMinPos.y + 1.f;
+        } else {
+            ball->delta.y += min(wallForce / (d * d * d), 10.f);
+        }
+    }
+
+    // low pressure ~500, high ~2500
+    pressure = max(pressure - 400.f, 0.f);
+    ball->pressure = pressure;
+
+    //rsDebug("p ", pressure);
+
+    float4 color = 1.f;
+    color.r = pow(pressure, 0.25f) / 12.f;
+    color.b = 1.f - color.r;
+    color.g = sin(pressure / 1500.f * 3.14f);
+    color.rgb = max(color.rgb, (float3)0);
+    color.rgb = normalize(color.rgb);
+    ball->color = rsPackColorTo8888(color);
+
+    //rsDebug("physics pos out", ball->position);
+}
+
diff --git a/java/tests/Balls/src/com/example/android/rs/balls/balls.rs b/java/tests/Balls/src/com/example/android/rs/balls/balls.rs
new file mode 100644
index 0000000..9be9f38
--- /dev/null
+++ b/java/tests/Balls/src/com/example/android/rs/balls/balls.rs
@@ -0,0 +1,106 @@
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.balls)
+#include "rs_graphics.rsh"
+
+#include "balls.rsh"
+
+#pragma stateVertex(parent)
+#pragma stateStore(parent)
+
+rs_program_fragment gPFPoints;
+rs_mesh partMesh;
+
+rs_allocation gGrid;
+BallGrid_t *unused1;
+float2 *gGridCache;
+
+typedef struct __attribute__((packed, aligned(4))) Point {
+    float2 position;
+    uchar4 color;
+} Point_t;
+Point_t *point;
+
+typedef struct VpConsts {
+    rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+
+rs_script physics_script;
+
+
+void initParts(int w, int h)
+{
+    uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls));
+
+    for (uint32_t ct=0; ct < dimX; ct++) {
+        balls[ct].position.x = rsRand(0.f, (float)w);
+        balls[ct].position.y = rsRand(0.f, (float)h);
+        balls[ct].delta.x = 0.f;
+        balls[ct].delta.y = 0.f;
+    }
+}
+
+int root() {
+    rsgClearColor(0.f, 0.f, 0.f, 1.f);
+
+    int2 gridDims = (int2){ rsAllocationGetDimX(gGrid),
+                            rsAllocationGetDimY(gGrid) };
+
+    rs_allocation ain = rsGetAllocation(balls);
+    int32_t dimX = rsAllocationGetDimX(ain);
+
+    // Binning
+    // Clear the particle list
+    for (uint32_t ct=0; ct < dimX; ct++) {
+        balls[ct].next = -1;
+    }
+
+    // Clear the grid
+    for (uint32_t y=0; y < gridDims.y; y++) {
+        for (uint32_t x=0; x < gridDims.x; x++) {
+            BallGrid_t *bg = (BallGrid_t *)rsGetElementAt(gGrid, x, y);
+            bg->count = 0;
+            bg->idx = -1;
+        }
+    }
+
+    // Create the particle list per grid
+    for (uint32_t ct=0; ct < dimX; ct++) {
+        int2 p = convert_int2(balls[ct].position / 100.f);
+        p.x = rsClamp(p.x, 0, (int)(gridDims.x-1));
+        p.y = rsClamp(p.y, 0, (int)(gridDims.y-1));
+        BallGrid_t *bg = (BallGrid_t *)rsGetElementAt(gGrid, p.x, p.y);
+        bg->count ++;
+        balls[ct].next = bg->idx;
+        bg->idx = ct;
+    }
+
+    // Create the sorted grid cache
+    uint32_t gridIdx = 0;
+    for (uint32_t y=0; y < gridDims.y; y++) {
+        for (uint32_t x=0; x < gridDims.x; x++) {
+            BallGrid_t *bg = (BallGrid_t *)rsGetElementAt(gGrid, x, y);
+            bg->cacheIdx = gridIdx;
+
+            int idx = bg->idx;
+            while (idx >= 0) {
+                const Ball_t * bPtr = &balls[idx];
+                gGridCache[gridIdx++] = bPtr->position;
+                idx = bPtr->next;
+            }
+        }
+    }
+
+
+    rsForEach(physics_script, ain, ain);
+
+    for (uint32_t ct=0; ct < dimX; ct++) {
+        point[ct].position = balls[ct].position;
+        point[ct].color = balls[ct].color;
+    }
+
+    rsgBindProgramFragment(gPFPoints);
+    rsgDrawMesh(partMesh);
+    return 1;
+}
+
diff --git a/java/tests/Balls/src/com/example/android/rs/balls/balls.rsh b/java/tests/Balls/src/com/example/android/rs/balls/balls.rsh
new file mode 100644
index 0000000..ebe23f8
--- /dev/null
+++ b/java/tests/Balls/src/com/example/android/rs/balls/balls.rsh
@@ -0,0 +1,19 @@
+
+typedef struct __attribute__((packed, aligned(4))) Ball {
+    float2 delta;
+    float2 position;
+    uchar4 color;
+    float pressure;
+    //float size;
+    int32_t next;
+    //int arcID;
+    //float arcStr;
+} Ball_t;
+Ball_t *balls;
+
+
+typedef struct BallGrid {
+    int32_t idx;
+    int32_t count;
+    int32_t cacheIdx;
+} BallGrid_t;
diff --git a/java/tests/ComputeBenchmark/Android.mk b/java/tests/ComputeBenchmark/Android.mk
new file mode 100644
index 0000000..8d47e89
--- /dev/null
+++ b/java/tests/ComputeBenchmark/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsComputeBenchmark
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/ComputeBenchmark/AndroidManifest.xml b/java/tests/ComputeBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..c8fcc17
--- /dev/null
+++ b/java/tests/ComputeBenchmark/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.computebench">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="_RS_Compute_Bench">
+        <activity android:name="ComputeBench">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/ComputeBenchmark/res/layout/main.xml b/java/tests/ComputeBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..9e9dab8
--- /dev/null
+++ b/java/tests/ComputeBenchmark/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java b/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.java
new file mode 100644
index 0000000..ec80719
--- /dev/null
+++ b/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/Benchmark.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 com.example.android.rs.computebench;
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class Benchmark implements Runnable {
+    private final RenderScript mRS;
+    private ScriptC_compute_benchmark mScript;
+
+    public Benchmark(RenderScript rs, Resources res) {
+        mRS = rs;
+        mScript = new ScriptC_compute_benchmark(mRS, res, R.raw.compute_benchmark);
+    }
+
+    public void run() {
+        long t = java.lang.System.currentTimeMillis();
+        mScript.invoke_bench();
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("ComputeBench", "Total benchmark took " + t + " ms");
+    }
+
+}
diff --git a/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java b/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java
new file mode 100644
index 0000000..2d3e843
--- /dev/null
+++ b/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/ComputeBench.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.example.android.rs.computebench;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+
+public class ComputeBench extends Activity {
+    private RenderScript mRS;
+    private Benchmark mBenchmark;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+
+        mBenchmark = new Benchmark(mRS, getResources());
+        mBenchmark.run();
+    }
+}
diff --git a/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs b/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
new file mode 100644
index 0000000..2ee56ec
--- /dev/null
+++ b/java/tests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
@@ -0,0 +1,407 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.computebench)
+
+// Test configuration (accessible from Java)
+uint priming_runs   = 1000000;
+uint timing_runs    = 5000000;
+
+// Reused variables
+
+static volatile int64_t bench_time;
+static float inv_timing_runs;
+
+#define DECL_VAR_SET(prefix)                \
+static volatile float prefix##_f_1 = 1;     \
+static volatile float2 prefix##_f_2 = 1;    \
+static volatile float3 prefix##_f_3 = 1;    \
+static volatile float4 prefix##_f_4 = 1;    \
+static volatile char prefix##_c_1 = 1;      \
+static volatile char2 prefix##_c_2 = 1;     \
+static volatile char3 prefix##_c_3 = 1;     \
+static volatile char4 prefix##_c_4 = 1;     \
+static volatile uchar prefix##_uc_1 = 1;    \
+static volatile uchar2 prefix##_uc_2 = 1;   \
+static volatile uchar3 prefix##_uc_3 = 1;   \
+static volatile uchar4 prefix##_uc_4 = 1;   \
+static volatile short prefix##_s_1 = 1;     \
+static volatile short2 prefix##_s_2 = 1;    \
+static volatile short3 prefix##_s_3 = 1;    \
+static volatile short4 prefix##_s_4 = 1;    \
+static volatile ushort prefix##_us_1 = 1;   \
+static volatile ushort2 prefix##_us_2 = 1;  \
+static volatile ushort3 prefix##_us_3 = 1;  \
+static volatile ushort4 prefix##_us_4 = 1;  \
+static volatile int prefix##_i_1 = 1;       \
+static volatile int2 prefix##_i_2 = 1;      \
+static volatile int3 prefix##_i_3 = 1;      \
+static volatile int4 prefix##_i_4 = 1;      \
+static volatile uint prefix##_ui_1 = 1;     \
+static volatile uint2 prefix##_ui_2 = 1;    \
+static volatile uint3 prefix##_ui_3 = 1;    \
+static volatile uint4 prefix##_ui_4 = 1;    \
+static volatile long prefix##_l_1 = 1;      \
+static volatile long2 prefix##_l_2 = 1;     \
+static volatile long3 prefix##_l_3 = 1;     \
+static volatile long4 prefix##_l_4 = 1;     \
+static volatile ulong prefix##_ul_1 = 1;    \
+static volatile ulong2 prefix##_ul_2 = 1;   \
+static volatile ulong3 prefix##_ul_3 = 1;   \
+static volatile ulong4 prefix##_ul_4 = 1;   \
+
+DECL_VAR_SET(res)
+DECL_VAR_SET(src1)
+DECL_VAR_SET(src2)
+DECL_VAR_SET(src3)
+
+
+// Testing macros
+
+#define RUN_BENCH(line, op)                         \
+    for (int i = priming_runs - 1; i >= 0; --i) {   \
+        line;                                       \
+    }                                               \
+    bench_time = rsUptimeMillis();                  \
+    for (int i = timing_runs - 1; i >= 0; --i) {    \
+        line;                                       \
+    }                                               \
+    bench_time = rsUptimeMillis() - bench_time;     \
+    rsDebug("    " op " took ns", (float)bench_time * inv_timing_runs);
+
+#define BENCH_BASIC_OP_TYPE(op, type)                                                               \
+    RUN_BENCH(res_##type##_1 = src1_##type##_1 op src2_##type##_1, #type "1 " #op " " #type "1")    \
+    RUN_BENCH(res_##type##_2 = src1_##type##_2 op src2_##type##_2, #type "2 " #op " " #type "2")    \
+    RUN_BENCH(res_##type##_3 = src1_##type##_3 op src2_##type##_3, #type "3 " #op " " #type "3")    \
+    RUN_BENCH(res_##type##_4 = src1_##type##_4 op src2_##type##_4, #type "4 " #op " " #type "4")    \
+
+#define BENCH_BASIC_INT_OP(op)                                  \
+    rsDebug("Testing basic operation " #op, 0);                 \
+    BENCH_BASIC_OP_TYPE(op, c)                                  \
+    BENCH_BASIC_OP_TYPE(op, uc)                                 \
+    BENCH_BASIC_OP_TYPE(op, s)                                  \
+    BENCH_BASIC_OP_TYPE(op, us)                                 \
+    BENCH_BASIC_OP_TYPE(op, i)                                  \
+    BENCH_BASIC_OP_TYPE(op, ui)                                 \
+    RUN_BENCH(res_l_1 = src1_l_1 op src2_l_1, "l1 " #op " l1")  \
+    RUN_BENCH(res_ul_1 = src1_ul_1 op src2_ul_1, "ul1 " #op " ul1")
+
+#define BENCH_BASIC_OP(op)      \
+    BENCH_BASIC_INT_OP(op)      \
+    BENCH_BASIC_OP_TYPE(op, f)
+
+#define BENCH_CVT(to, from, type)                                                                           \
+    rsDebug("Testing convert from " #from " to " #to, 0);                                                   \
+    RUN_BENCH(res_##to##_1 = (type)src1_##from##_1, "(" #to ")" #from)                                      \
+    RUN_BENCH(res_##to##_2 = convert_##type##2(src1_##from##_2), #to "2 convert_" #type "2(" #from "2)")    \
+    RUN_BENCH(res_##to##_3 = convert_##type##3(src1_##from##_3), #to "3 convert_" #type "3(" #from "3)")    \
+    RUN_BENCH(res_##to##_4 = convert_##type##4(src1_##from##_4), #to "4 convert_" #type "4(" #from "4)")
+
+#define BENCH_CVT_MATRIX(to, type)  \
+    BENCH_CVT(to, c, type);         \
+    BENCH_CVT(to, uc, type);        \
+    BENCH_CVT(to, s, type);         \
+    BENCH_CVT(to, us, type);        \
+    BENCH_CVT(to, i, type);         \
+    BENCH_CVT(to, ui, type);        \
+    BENCH_CVT(to, f, type);         \
+
+#define BENCH_XN_FUNC_YN(typeout, fnc, typein)                                                  \
+    RUN_BENCH(res_##typeout##_1 = fnc(src1_##typein##_1);, #typeout "1 " #fnc "(" #typein "1)") \
+    RUN_BENCH(res_##typeout##_2 = fnc(src1_##typein##_2);, #typeout "2 " #fnc "(" #typein "2)") \
+    RUN_BENCH(res_##typeout##_3 = fnc(src1_##typein##_3);, #typeout "3 " #fnc "(" #typein "3)") \
+    RUN_BENCH(res_##typeout##_4 = fnc(src1_##typein##_4);, #typeout "4 " #fnc "(" #typein "4)")
+
+#define BENCH_XN_FUNC_XN_XN(type, fnc)                                                                              \
+    RUN_BENCH(res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1), #type "1 " #fnc "(" #type "1, " #type "1)")   \
+    RUN_BENCH(res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2), #type "2 " #fnc "(" #type "2, " #type "2)")   \
+    RUN_BENCH(res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3), #type "3 " #fnc "(" #type "3, " #type "3)")   \
+    RUN_BENCH(res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4), #type "4 " #fnc "(" #type "4, " #type "4)")   \
+
+#define BENCH_X_FUNC_X_X_X(type, fnc)   \
+    RUN_BENCH(res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src3_##type##_1), #type "1 " #fnc "(" #type "1, " #type "1, " #type "1)")
+
+#define BENCH_IN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_XN_FUNC_YN(uc, fnc, uc)   \
+    BENCH_XN_FUNC_YN(c, fnc, c)     \
+    BENCH_XN_FUNC_YN(us, fnc, us)   \
+    BENCH_XN_FUNC_YN(s, fnc, s)     \
+    BENCH_XN_FUNC_YN(ui, fnc, ui)   \
+    BENCH_XN_FUNC_YN(i, fnc, i)
+
+#define BENCH_UIN_FUNC_IN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_XN_FUNC_YN(uc, fnc, c)    \
+    BENCH_XN_FUNC_YN(us, fnc, s)    \
+    BENCH_XN_FUNC_YN(ui, fnc, i)    \
+
+#define BENCH_IN_FUNC_IN_IN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_XN_FUNC_XN_XN(uc, fnc)    \
+    BENCH_XN_FUNC_XN_XN(c, fnc)     \
+    BENCH_XN_FUNC_XN_XN(us, fnc)    \
+    BENCH_XN_FUNC_XN_XN(s, fnc)     \
+    BENCH_XN_FUNC_XN_XN(ui, fnc)    \
+    BENCH_XN_FUNC_XN_XN(i, fnc)
+
+#define BENCH_I_FUNC_I_I_I(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    BENCH_X_FUNC_X_X_X(uc, fnc)     \
+    BENCH_X_FUNC_X_X_X(c, fnc)      \
+    BENCH_X_FUNC_X_X_X(us, fnc)     \
+    BENCH_X_FUNC_X_X_X(s, fnc)      \
+    BENCH_X_FUNC_X_X_X(ui, fnc)     \
+    BENCH_X_FUNC_X_X_X(i, fnc)
+
+#define BENCH_FN_FUNC_FN(fnc)                               \
+    rsDebug("Testing " #fnc, 0);                            \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1), "f1 " #fnc "(f1)")   \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2), "f2 " #fnc "(f2)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3), "f3 " #fnc "(f3)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4), "f4 " #fnc "(f4)")
+
+#define BENCH_FN_FUNC_FN_PFN(fnc)                                                   \
+    rsDebug("Testing " #fnc, 0);                                                    \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, (float*) &src2_f_1), "f1 " #fnc "(f1, f1*)")  \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, (float2*) &src2_f_2), "f2 " #fnc "(f2, f2*)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, (float3*) &src2_f_3), "f3 " #fnc "(f3, f3*)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, (float4*) &src2_f_4), "f4 " #fnc "(f4, f4*)")
+
+#define BENCH_FN_FUNC_FN_FN(fnc)                                        \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2), "f2 " #fnc "(f2, f2)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3), "f3 " #fnc "(f3, f3)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4), "f4 " #fnc "(f4, f4)")
+
+#define BENCH_F34_FUNC_F34_F34(fnc)                                     \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3), "f3 " #fnc "(f3, f3)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4), "f4 " #fnc "(f4, f4)")
+
+#define BENCH_FN_FUNC_FN_F(fnc)                                         \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_1), "f2 " #fnc "(f2, f1)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_1), "f3 " #fnc "(f3, f1)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_1), "f4 " #fnc "(f4, f1)")
+
+#define BENCH_F_FUNC_FN(fnc)                                \
+    rsDebug("Testing " #fnc, 0);                            \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1), "f1 " #fnc "(f1)")   \
+    RUN_BENCH(res_f_1 = fnc(src1_f_2), "f1 " #fnc "(f2)")   \
+    RUN_BENCH(res_f_1 = fnc(src1_f_3), "f1 " #fnc "(f3)")   \
+    RUN_BENCH(res_f_1 = fnc(src1_f_4), "f1 " #fnc "(f4)")
+
+#define BENCH_F_FUNC_FN_FN(fnc)                                         \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1), "f1 " #fnc "(f1, f1)") \
+    RUN_BENCH(res_f_1 = fnc(src1_f_2, src2_f_2), "f1 " #fnc "(f2, f2)") \
+    RUN_BENCH(res_f_1 = fnc(src1_f_3, src2_f_3), "f1 " #fnc "(f3, f3)") \
+    RUN_BENCH(res_f_1 = fnc(src1_f_4, src2_f_4), "f1 " #fnc "(f4, f4)")
+
+#define BENCH_FN_FUNC_FN_IN(fnc)                                        \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src1_i_1), "f1 " #fnc "(f1, i1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src1_i_2), "f2 " #fnc "(f2, i2)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src1_i_3), "f3 " #fnc "(f3, i3)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src1_i_4), "f4 " #fnc "(f4, i4)")
+
+#define BENCH_FN_FUNC_FN_I(fnc)                                         \
+    rsDebug("Testing " #fnc, 0);                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src1_i_1), "f1 " #fnc "(f1, i1)") \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src1_i_1), "f2 " #fnc "(f2, i1)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src1_i_1), "f3 " #fnc "(f3, i1)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src1_i_1), "f4 " #fnc "(f4, i1)")
+
+#define BENCH_FN_FUNC_FN_FN_FN(fnc)                                                     \
+    rsDebug("Testing " #fnc, 0);                                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, src3_f_1), "f1 " #fnc "(f1, f1, f1)")   \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, src3_f_2), "f2 " #fnc "(f2, f2, f2)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, src3_f_3), "f3 " #fnc "(f3, f3, f3)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, src3_f_4), "f4 " #fnc "(f4, f4, f4)")
+
+#define BENCH_FN_FUNC_FN_FN_F(fnc)                                                      \
+    rsDebug("Testing " #fnc, 0);                                                        \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, src3_f_1), "f1 " #fnc "(f1, f1, f1)")   \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, src3_f_1), "f2 " #fnc "(f2, f2, f1)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, src3_f_1), "f3 " #fnc "(f3, f3, f1)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, src3_f_1), "f4 " #fnc "(f4, f4, f1)")
+
+#define BENCH_FN_FUNC_FN_PIN(fnc)                                                   \
+    rsDebug("Testing " #fnc, 0);                                                    \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, (int*) &src1_i_1), "f1 " #fnc "(f1, i1*)")    \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, (int2*) &src1_i_2), "f2 " #fnc "(f2, i2*)")   \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, (int3*) &src1_i_3), "f3 " #fnc "(f3, i3*)")   \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, (int4*) &src1_i_4), "f4 " #fnc "(f4, i4*)")
+
+#define BENCH_FN_FUNC_FN_FN_PIN(fnc)                                                            \
+    rsDebug("Testing " #fnc, 0);                                                                \
+    RUN_BENCH(res_f_1 = fnc(src1_f_1, src2_f_1, (int*) &src1_i_1), "f1 " #fnc "(f1, f1, i1*)")  \
+    RUN_BENCH(res_f_2 = fnc(src1_f_2, src2_f_2, (int2*) &src1_i_2), "f2 " #fnc "(f2, f2, i2*)") \
+    RUN_BENCH(res_f_3 = fnc(src1_f_3, src2_f_3, (int3*) &src1_i_3), "f3 " #fnc "(f3, f3, i3*)") \
+    RUN_BENCH(res_f_4 = fnc(src1_f_4, src2_f_4, (int4*) &src1_i_4), "f4 " #fnc "(f4, f4, i4*)")
+
+#define BENCH_IN_FUNC_FN(fnc)                               \
+    rsDebug("Testing " #fnc, 0);                            \
+    RUN_BENCH(res_i_1 = fnc(src1_f_1), "i1 " #fnc "(f1)")   \
+    RUN_BENCH(res_i_2 = fnc(src1_f_2), "i2 " #fnc "(f2)")   \
+    RUN_BENCH(res_i_3 = fnc(src1_f_3), "i3 " #fnc "(f3)")   \
+    RUN_BENCH(res_i_4 = fnc(src1_f_4), "i4 " #fnc "(f4)")
+
+
+// Testing functions
+
+static void bench_basic_operators() {
+    int i = 0;
+    BENCH_BASIC_OP(+);
+    BENCH_BASIC_OP(-);
+    BENCH_BASIC_OP(*);
+    BENCH_BASIC_OP(/);
+    BENCH_BASIC_INT_OP(%);
+    BENCH_BASIC_INT_OP(<<);
+    BENCH_BASIC_INT_OP(>>);
+}
+
+static void bench_convert() {
+    BENCH_CVT_MATRIX(c, char);
+    BENCH_CVT_MATRIX(uc, uchar);
+    BENCH_CVT_MATRIX(s, short);
+    BENCH_CVT_MATRIX(us, ushort);
+    BENCH_CVT_MATRIX(i, int);
+    BENCH_CVT_MATRIX(ui, uint);
+    BENCH_CVT_MATRIX(f, float);
+}
+
+static void bench_int_math() {
+    BENCH_UIN_FUNC_IN(abs);
+    BENCH_IN_FUNC_IN(clz);
+    BENCH_IN_FUNC_IN_IN(min);
+    BENCH_IN_FUNC_IN_IN(max);
+    BENCH_I_FUNC_I_I_I(rsClamp);
+}
+
+static void bench_fp_math() {
+    BENCH_FN_FUNC_FN(acos);
+    BENCH_FN_FUNC_FN(acosh);
+    BENCH_FN_FUNC_FN(acospi);
+    BENCH_FN_FUNC_FN(asin);
+    BENCH_FN_FUNC_FN(asinh);
+    BENCH_FN_FUNC_FN(asinpi);
+    BENCH_FN_FUNC_FN(atan);
+    BENCH_FN_FUNC_FN_FN(atan2);
+    BENCH_FN_FUNC_FN(atanh);
+    BENCH_FN_FUNC_FN(atanpi);
+    BENCH_FN_FUNC_FN_FN(atan2pi);
+    BENCH_FN_FUNC_FN(cbrt);
+    BENCH_FN_FUNC_FN(ceil);
+    BENCH_FN_FUNC_FN_FN_FN(clamp);
+    BENCH_FN_FUNC_FN_FN_F(clamp);
+    BENCH_FN_FUNC_FN_FN(copysign);
+    BENCH_FN_FUNC_FN(cos);
+    BENCH_FN_FUNC_FN(cosh);
+    BENCH_FN_FUNC_FN(cospi);
+    BENCH_F34_FUNC_F34_F34(cross);
+    BENCH_FN_FUNC_FN(degrees);
+    BENCH_F_FUNC_FN_FN(distance);
+    BENCH_F_FUNC_FN_FN(dot);
+    BENCH_FN_FUNC_FN(erfc);
+    BENCH_FN_FUNC_FN(erf);
+    BENCH_FN_FUNC_FN(exp);
+    BENCH_FN_FUNC_FN(exp2);
+    BENCH_FN_FUNC_FN(exp10);
+    BENCH_FN_FUNC_FN(expm1);
+    BENCH_FN_FUNC_FN(fabs);
+    BENCH_FN_FUNC_FN_FN(fdim);
+    BENCH_FN_FUNC_FN(floor);
+    BENCH_FN_FUNC_FN_FN_FN(fma);
+    BENCH_FN_FUNC_FN_FN(fmax);
+    BENCH_FN_FUNC_FN_F(fmax);
+    BENCH_FN_FUNC_FN_FN(fmin);
+    BENCH_FN_FUNC_FN_F(fmin);
+    BENCH_FN_FUNC_FN_FN(fmod);
+    BENCH_FN_FUNC_FN_PFN(fract);
+    BENCH_FN_FUNC_FN_PIN(frexp);
+    BENCH_FN_FUNC_FN_FN(hypot);
+    BENCH_IN_FUNC_FN(ilogb);
+    BENCH_FN_FUNC_FN_IN(ldexp);
+    BENCH_FN_FUNC_FN_I(ldexp);
+    BENCH_F_FUNC_FN(length);
+    BENCH_FN_FUNC_FN(lgamma);
+    BENCH_FN_FUNC_FN_PIN(lgamma);
+    BENCH_FN_FUNC_FN(log);
+    BENCH_FN_FUNC_FN(log2);
+    BENCH_FN_FUNC_FN(log10);
+    BENCH_FN_FUNC_FN(log1p);
+    BENCH_FN_FUNC_FN(logb);
+    BENCH_FN_FUNC_FN_FN_FN(mad);
+    BENCH_FN_FUNC_FN_FN(max);
+    BENCH_FN_FUNC_FN_F(max);
+    BENCH_FN_FUNC_FN_FN(min);
+    BENCH_FN_FUNC_FN_F(min);
+    BENCH_FN_FUNC_FN_FN_FN(mix);
+    BENCH_FN_FUNC_FN_FN_F(mix);
+    BENCH_FN_FUNC_FN_PFN(modf);
+    BENCH_FN_FUNC_FN_FN(nextafter);
+    BENCH_FN_FUNC_FN(normalize);
+    BENCH_FN_FUNC_FN_FN(pow);
+    BENCH_FN_FUNC_FN_IN(pown);
+    BENCH_FN_FUNC_FN_FN(powr);
+    BENCH_FN_FUNC_FN(radians);
+    BENCH_FN_FUNC_FN_FN(remainder);
+    BENCH_FN_FUNC_FN_FN_PIN(remquo);
+    BENCH_FN_FUNC_FN(rint);
+    BENCH_FN_FUNC_FN_IN(rootn);
+    BENCH_FN_FUNC_FN(round);
+    BENCH_FN_FUNC_FN(rsqrt);
+    BENCH_FN_FUNC_FN(sign);
+    BENCH_FN_FUNC_FN(sin);
+    BENCH_FN_FUNC_FN_PFN(sincos);
+    BENCH_FN_FUNC_FN(sinh);
+    BENCH_FN_FUNC_FN(sinpi);
+    BENCH_FN_FUNC_FN(sqrt);
+    BENCH_FN_FUNC_FN_FN(step);
+    BENCH_FN_FUNC_FN_F(step);
+    BENCH_FN_FUNC_FN(tan);
+    BENCH_FN_FUNC_FN(tanh);
+    BENCH_FN_FUNC_FN(tanpi);
+    BENCH_FN_FUNC_FN(tgamma);
+    BENCH_FN_FUNC_FN(trunc);
+}
+
+static void bench_approx_math() {
+    BENCH_FN_FUNC_FN(half_recip);
+    BENCH_FN_FUNC_FN(half_sqrt);
+    BENCH_FN_FUNC_FN(half_rsqrt);
+    BENCH_FN_FUNC_FN(fast_length);
+    BENCH_FN_FUNC_FN_FN(fast_distance);
+    BENCH_FN_FUNC_FN(fast_normalize);
+}
+
+void bench() {
+    rsDebug("RS Compute Benchmark", 0);
+    rsDebug("Current configuration:", 0);
+    rsDebug("Priming runs", priming_runs);
+    rsDebug("Timing runs", timing_runs);
+    rsDebug("Beginning test", 0);
+    inv_timing_runs = 1000000.f / (float)timing_runs;
+    bench_basic_operators();
+    bench_convert();
+    bench_int_math();
+    bench_fp_math();
+    bench_approx_math();
+}
+
diff --git a/java/tests/ComputePerf/Android.mk b/java/tests/ComputePerf/Android.mk
new file mode 100644
index 0000000..6ed5884
--- /dev/null
+++ b/java/tests/ComputePerf/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsComputePerf
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/ComputePerf/AndroidManifest.xml b/java/tests/ComputePerf/AndroidManifest.xml
new file mode 100644
index 0000000..a9193b5
--- /dev/null
+++ b/java/tests/ComputePerf/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.computeperf">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    
+    <uses-sdk android:minSdkVersion="14" />
+    <application android:label="Compute Perf">
+        <activity android:name="ComputePerf">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/ComputePerf/res/layout/main.xml b/java/tests/ComputePerf/res/layout/main.xml
new file mode 100644
index 0000000..61cd24d
--- /dev/null
+++ b/java/tests/ComputePerf/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/java/tests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java
new file mode 100644
index 0000000..5446f66
--- /dev/null
+++ b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.computeperf;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.util.Log;
+import android.widget.ImageView;
+
+public class ComputePerf extends Activity {
+    private LaunchTest mLT;
+    private Mandelbrot mMandel;
+    private RenderScript mRS;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        final int numTries = 100;
+
+        long timesXLW = 0;
+        long timesXYW = 0;
+
+        mRS = RenderScript.create(this);
+        mLT = new LaunchTest(mRS, getResources());
+        mLT.XLW();
+        mLT.XYW();
+        for (int i = 0; i < numTries; i++) {
+            timesXLW += mLT.XLW();
+            timesXYW += mLT.XYW();
+        }
+
+        timesXLW /= numTries;
+        timesXYW /= numTries;
+
+        // XLW and XYW running times should match pretty closely
+        Log.v("ComputePerf", "xlw launch test " + timesXLW + "ms");
+        Log.v("ComputePerf", "xyw launch test " + timesXYW + "ms");
+
+        mMandel = new Mandelbrot(mRS, getResources());
+        mMandel.run();
+    }
+}
diff --git a/java/tests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java
new file mode 100644
index 0000000..e2312ba
--- /dev/null
+++ b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.computeperf;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class LaunchTest {
+    private RenderScript mRS;
+    private Allocation mAllocationX;
+    private Allocation mAllocationXY;
+    private ScriptC_launchtestxlw mScript_xlw;
+    private ScriptC_launchtestxyw mScript_xyw;
+
+    LaunchTest(RenderScript rs, Resources res) {
+        mRS = rs;
+        mScript_xlw = new ScriptC_launchtestxlw(mRS, res, R.raw.launchtestxlw);
+        mScript_xyw = new ScriptC_launchtestxyw(mRS, res, R.raw.launchtestxyw);
+        final int dim = mScript_xlw.get_dim();
+
+        mAllocationX = Allocation.createSized(rs, Element.U8(rs), dim);
+        Type.Builder tb = new Type.Builder(rs, Element.U8(rs));
+        tb.setX(dim);
+        tb.setY(dim);
+        mAllocationXY = Allocation.createTyped(rs, tb.create());
+        mScript_xlw.bind_buf(mAllocationXY);
+    }
+
+    public long XLW() {
+        long t = java.lang.System.currentTimeMillis();
+        mScript_xlw.forEach_root(mAllocationX);
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        return t;
+    }
+
+    public long XYW() {
+        long t = java.lang.System.currentTimeMillis();
+        mScript_xyw.forEach_root(mAllocationXY);
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        return t;
+    }
+}
diff --git a/java/tests/ComputePerf/src/com/example/android/rs/computeperf/Mandelbrot.java b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/Mandelbrot.java
new file mode 100644
index 0000000..ea1cd62
--- /dev/null
+++ b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/Mandelbrot.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.example.android.rs.computeperf;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class Mandelbrot implements Runnable {
+    private RenderScript mRS;
+    private Allocation mAllocationXY;
+    private ScriptC_mandelbrot mScript;
+
+    Mandelbrot(RenderScript rs, Resources res) {
+        mRS = rs;
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+
+        Type.Builder tb = new Type.Builder(rs, Element.U8_4(rs));
+        tb.setX(mScript.get_gDimX());
+        tb.setY(mScript.get_gDimY());
+        mAllocationXY = Allocation.createTyped(rs, tb.create());
+    }
+
+    public void run() {
+        long t = java.lang.System.currentTimeMillis();
+        mScript.forEach_root(mAllocationXY);
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("ComputePerf", "mandelbrot  ms " + t);
+    }
+
+}
diff --git a/java/tests/ComputePerf/src/com/example/android/rs/computeperf/launchtestxlw.rs b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/launchtestxlw.rs
new file mode 100644
index 0000000..7b81dfe
--- /dev/null
+++ b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/launchtestxlw.rs
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.computeperf)
+
+const int dim = 2048;
+uint8_t *buf;
+
+void root(uchar *v_out, uint32_t x) {
+    uint8_t *p = buf;
+    p += x * dim;
+    for (int i=0; i<dim; i++) {
+        p[i] = 1;
+    }
+}
+
diff --git a/java/tests/ComputePerf/src/com/example/android/rs/computeperf/launchtestxyw.rs b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/launchtestxyw.rs
new file mode 100644
index 0000000..7f7aa95
--- /dev/null
+++ b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/launchtestxyw.rs
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.computeperf)
+
+void root(uchar *v_out, uint32_t x, uint32_t y) {
+    *v_out = 0;
+}
+
diff --git a/java/tests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
new file mode 100644
index 0000000..0ffb0e5
--- /dev/null
+++ b/java/tests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
@@ -0,0 +1,43 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.computeperf)
+
+const int gMaxIteration = 500;
+const int gDimX = 1024;
+const int gDimY = 1024;
+
+void root(uchar4 *v_out, uint32_t x, uint32_t y) {
+    float2 p;
+    p.x = -2.5f + ((float)x / gDimX) * 3.5f;
+    p.y = -1.f + ((float)y / gDimY) * 2.f;
+
+    float2 t = 0;
+    float2 t2 = t * t;
+    int iteration = 0;
+    while((t2.x + t2.y < 4.f) && (iteration < gMaxIteration)) {
+        float xtemp = t2.x - t2.y + p.x;
+        t.y = 2 * t.x * t.y + p.y;
+        t.x = xtemp;
+        iteration++;
+        t2 = t * t;
+    }
+
+    if(iteration >= gMaxIteration) {
+        *v_out = 0;
+    } else {
+        *v_out = (uchar4){iteration & 0xff, (iteration >> 6) & 0xff, 0x8f, 0xff};
+    }
+}
diff --git a/java/tests/ImageProcessing/Android.mk b/java/tests/ImageProcessing/Android.mk
new file mode 100644
index 0000000..d7486e8
--- /dev/null
+++ b/java/tests/ImageProcessing/Android.mk
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := ImageProcessing
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/ImageProcessing/AndroidManifest.xml b/java/tests/ImageProcessing/AndroidManifest.xml
new file mode 100644
index 0000000..d51fa39
--- /dev/null
+++ b/java/tests/ImageProcessing/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.image">
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="Image Processing"
+                 android:hardwareAccelerated="true">
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="ImageProcessingActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name=".ImageProcessingTestRunner"
+      android:targetPackage="com.android.rs.image"
+      android:label="Test runner for Image Processing Benchmark Test"
+    />
+</manifest>
diff --git a/java/tests/ImageProcessing/res/drawable-nodpi/img1600x1067.jpg b/java/tests/ImageProcessing/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/java/tests/ImageProcessing/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg b/java/tests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/java/tests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing/res/layout/main.xml b/java/tests/ImageProcessing/res/layout/main.xml
new file mode 100644
index 0000000..f0a2b92
--- /dev/null
+++ b/java/tests/ImageProcessing/res/layout/main.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider1Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/slider1"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider2Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/slider2"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider3Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/slider3"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider4Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider4"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider5Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider5"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/java/tests/ImageProcessing/res/layout/spinner_layout.xml b/java/tests/ImageProcessing/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/java/tests/ImageProcessing/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/java/tests/ImageProcessing/res/values/strings.xml b/java/tests/ImageProcessing/res/values/strings.xml
new file mode 100644
index 0000000..a7dd165
--- /dev/null
+++ b/java/tests/ImageProcessing/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <!--slider label -->
+    <string name="blur_description">Blur Radius</string>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
+
+</resources>
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/BWFilter.java b/java/tests/ImageProcessing/src/com/android/rs/image/BWFilter.java
new file mode 100644
index 0000000..64be4aa
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/BWFilter.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+
+public class BWFilter extends TestBase {
+    private ScriptC_bwfilter mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_bwfilter(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_prepareBwFilter(50, 50, 50);
+        mScript.forEach_bwFilterKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Blend.java b/java/tests/ImageProcessing/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..2303fc3
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Blend.java
@@ -0,0 +1,178 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicBlend;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    if (mRS != null) {
+                        runTest();
+                        act.updateDisplay();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Blur25.java b/java/tests/ImageProcessing/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..0c6d41d
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
+
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
+    }
+
+    public void setupBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
+    }
+
+    public void exitBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Blur25G.java b/java/tests/ImageProcessing/src/com/android/rs/image/Blur25G.java
new file mode 100644
index 0000000..ac0dad1
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Blur25G.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.graphics.Bitmap;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25G extends TestBase {
+    private final int MAX_RADIUS = 25;
+    private float mRadius = MAX_RADIUS;
+
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private ScriptC_greyscale mScript;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25G() {
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        mIntrinsic.setRadius(mRadius);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_greyscale(mRS);
+        mScript.forEach_toU8(mInPixelsAllocation, mScratchPixelsAllocation1);
+
+        mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8(mRS));
+        mIntrinsic.setRadius(MAX_RADIUS);
+        mIntrinsic.setInput(mScratchPixelsAllocation1);
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mScratchPixelsAllocation2);
+    }
+
+    public void setupBenchmark() {
+        mIntrinsic.setRadius(MAX_RADIUS);
+    }
+
+    public void exitBenchmark() {
+        mIntrinsic.setRadius(mRadius);
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mScript.forEach_toU8_4(mScratchPixelsAllocation2, mOutPixelsAllocation);
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/ColorCube.java b/java/tests/ImageProcessing/src/com/android/rs/image/ColorCube.java
new file mode 100644
index 0000000..f313c46
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/ColorCube.java
@@ -0,0 +1,88 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsic3DLUT;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class ColorCube extends TestBase {
+    private Allocation mCube;
+    private ScriptC_colorcube mScript;
+    private ScriptIntrinsic3DLUT mIntrinsic;
+    private boolean mUseIntrinsic;
+
+    public ColorCube(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    private void initCube() {
+        final int sx = 32;
+        final int sy = 32;
+        final int sz = 16;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(sx);
+        tb.setY(sy);
+        tb.setZ(sz);
+        Type t = tb.create();
+        mCube = Allocation.createTyped(mRS, t);
+
+        int dat[] = new int[sx * sy * sz];
+        for (int z = 0; z < sz; z++) {
+            for (int y = 0; y < sy; y++) {
+                for (int x = 0; x < sx; x++ ) {
+                    int v = 0xff000000;
+                    v |= (0xff * x / (sx - 1));
+                    v |= (0xff * y / (sy - 1)) << 8;
+                    v |= (0xff * z / (sz - 1)) << 16;
+                    dat[z*sy*sx + y*sx + x] = v;
+                }
+            }
+        }
+
+        mCube.copyFromUnchecked(dat);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_colorcube(mRS, res, R.raw.colorcube);
+        mIntrinsic = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+
+        initCube();
+        mScript.invoke_setCube(mCube);
+        mIntrinsic.setLUT(mCube);
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/ColorMatrix.java b/java/tests/ImageProcessing/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..2ac40a1
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Contrast.java b/java/tests/ImageProcessing/src/com/android/rs/image/Contrast.java
new file mode 100644
index 0000000..f3cf1b7
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Contrast.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Contrast extends TestBase {
+    private ScriptC_contrast mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_contrast(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_setBright(50.f);
+        mScript.forEach_contrast(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Convolve3x3.java b/java/tests/ImageProcessing/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..18e9b43
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,74 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java b/java/tests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..03b3bb8
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,88 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve5x5;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Copy.java b/java/tests/ImageProcessing/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..efca0b5
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Copy.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/CrossProcess.java b/java/tests/ImageProcessing/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..b9e3524
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicLUT;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Exposure.java b/java/tests/ImageProcessing/src/com/android/rs/image/Exposure.java
new file mode 100644
index 0000000..bec53ab
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Exposure.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Exposure extends TestBase {
+    private ScriptC_exposure mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_exposure(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_setBright(50.f);
+        mScript.forEach_exposure(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Fisheye.java b/java/tests/ImageProcessing/src/com/android/rs/image/Fisheye.java
new file mode 100644
index 0000000..81868b1
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,138 @@
+/*
+ * 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 com.android.rs.image;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Fisheye extends TestBase {
+    private ScriptC_fisheye_full mScript_full = null;
+    private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+        else
+            mScript_full.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
+            mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
+                    R.raw.fisheye_relaxed);
+            mScript_relaxed.set_in_alloc(mInPixelsAllocation);
+            mScript_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        } else {
+            mScript_full = new ScriptC_fisheye_full(mRS, res,
+                    R.raw.fisheye_full);
+            mScript_full.set_in_alloc(mInPixelsAllocation);
+            mScript_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        }
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Grain.java b/java/tests/ImageProcessing/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..8618cc8
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Grain.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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(noiseW);
+        tb.setY(noiseH);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Greyscale.java b/java/tests/ImageProcessing/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..3db210a
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/GroupTest.java b/java/tests/ImageProcessing/src/com/android/rs/image/GroupTest.java
new file mode 100644
index 0000000..29c204c
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/GroupTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.renderscript.Matrix4f;
+import android.renderscript.ScriptGroup;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
+
+    private Allocation mScratchPixelsAllocation1;
+    private ScriptGroup mGroup;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseNative;
+
+
+    public GroupTest(boolean useNative) {
+        mUseNative = useNative;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+        mConvolve.setCoefficients(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.setColorMatrix(m);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        Type connect = tb.create();
+
+        if (mUseNative) {
+            ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
+            mGroup = b.create();
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.setInput(mInPixelsAllocation);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
new file mode 100644
index 0000000..8cf46c2
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -0,0 +1,557 @@
+/*
+ * 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 com.android.rs.image;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.view.SurfaceView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+
+import android.os.Environment;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class ImageProcessingActivity extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    public final String RESULT_FILE = "image_processing_result.csv";
+
+    RenderScript mRS;
+    Allocation mInPixelsAllocation;
+    Allocation mInPixelsAllocation2;
+    Allocation mOutPixelsAllocation;
+
+    /**
+     * Define enum type for test names
+     */
+    public enum TestName {
+        // totally there are 38 test cases
+        LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
+        LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
+        LEVELS_VEC3_FULL ("Levels Vec3 Full"),
+        LEVELS_VEC4_FULL ("Levels Vec4 Full"),
+        BLUR_RADIUS_25 ("Blur radius 25"),
+        INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
+        GREYSCALE ("Greyscale"),
+        GRAIN ("Grain"),
+        FISHEYE_FULL ("Fisheye Full"),
+        FISHEYE_RELAXED ("Fisheye Relaxed"),
+        FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
+        FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
+        VIGNETTE_FULL ("Vignette Full"),
+        VIGNETTE_RELAXED ("Vignette Relaxed"),
+        VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
+        VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
+        GROUP_TEST_EMULATED ("Group Test (emulated)"),
+        GROUP_TEST_NATIVE ("Group Test (native)"),
+        CONVOLVE_3X3 ("Convolve 3x3"),
+        INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
+        COLOR_MATRIX ("ColorMatrix"),
+        INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
+        INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
+        COPY ("Copy"),
+        CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
+        CONVOLVE_5X5 ("Convolve 5x5"),
+        INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
+        MANDELBROT ("Mandelbrot"),
+        INTRINSICS_BLEND ("Intrinsics Blend"),
+        INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar"),
+        VIBRANCE ("Vibrance"),
+        BW_FILTER ("BW Filter"),
+        SHADOWS ("Shadows"),
+        CONTRAST ("Contrast"),
+        EXPOSURE ("Exposure"),
+        WHITE_BALANCE ("White Balance"),
+        COLOR_CUBE ("Color Cube"),
+        COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)"),
+        USAGE_IO ("Usage io)");
+
+
+        private final String name;
+
+        private TestName(String s) {
+            name = s;
+        }
+
+        // return quoted string as displayed test name
+        public String toString() {
+            return name;
+        }
+    }
+
+    Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
+    Bitmap mBitmapOut;
+
+    private Spinner mSpinner;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
+
+    private float mSaturation = 1.0f;
+
+    private TextView mBenchmarkResult;
+    private Spinner mTestSpinner;
+
+    private SurfaceView mSurfaceView;
+    private ImageView mDisplayView;
+
+    private boolean mDoingBenchmark;
+
+    private TestBase mTest;
+    private int mRunCount;
+
+    public void updateDisplay() {
+        mHandler.sendMessage(Message.obtain());
+    }
+
+    private Handler mHandler = new Handler() {
+        // Allow the filter to complete without blocking the UI
+        // thread.  When the message arrives that the op is complete
+        // we will either mark completion or start a new filter if
+        // more work is ready.  Either way, display the result.
+        @Override
+        public void handleMessage(Message msg) {
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRS == null) {
+                    return;
+                }
+                mTest.updateBitmap(mBitmapOut);
+                mDisplayView.invalidate();
+                if (mRunCount > 0) {
+                    mRunCount--;
+                    if (mRunCount > 0) {
+                        doTest = true;
+                    }
+                }
+
+                if (doTest) {
+                    mTest.runTestSendMessage();
+                }
+            }
+        }
+
+    };
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
+            }
+
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount == 0) {
+                    doTest = true;
+                    mRunCount = 1;
+                } else {
+                    mRunCount = 2;
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(TestName testName) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
+        switch(testName) {
+        case LEVELS_VEC3_RELAXED:
+            mTest = new LevelsV4(false, false);
+            break;
+        case LEVELS_VEC4_RELAXED:
+            mTest = new LevelsV4(false, true);
+            break;
+        case LEVELS_VEC3_FULL:
+            mTest = new LevelsV4(true, false);
+            break;
+        case LEVELS_VEC4_FULL:
+            mTest = new LevelsV4(true, true);
+            break;
+        case BLUR_RADIUS_25:
+            mTest = new Blur25(false);
+            break;
+        case INTRINSIC_BLUE_RADIUS_25:
+            mTest = new Blur25(true);
+            break;
+        case GREYSCALE:
+            mTest = new Greyscale();
+            break;
+        case GRAIN:
+            mTest = new Grain();
+            break;
+        case FISHEYE_FULL:
+            mTest = new Fisheye(false, false);
+            break;
+        case FISHEYE_RELAXED:
+            mTest = new Fisheye(false, true);
+            break;
+        case FISHEYE_APPROXIMATE_FULL:
+            mTest = new Fisheye(true, false);
+            break;
+        case FISHEYE_APPROXIMATE_RELAXED:
+            mTest = new Fisheye(true, true);
+            break;
+        case VIGNETTE_FULL:
+            mTest = new Vignette(false, false);
+            break;
+        case VIGNETTE_RELAXED:
+            mTest = new Vignette(false, true);
+            break;
+        case VIGNETTE_APPROXIMATE_FULL:
+            mTest = new Vignette(true, false);
+            break;
+        case VIGNETTE_APPROXIMATE_RELAXED:
+            mTest = new Vignette(true, true);
+            break;
+        case GROUP_TEST_EMULATED:
+            mTest = new GroupTest(false);
+            break;
+        case GROUP_TEST_NATIVE:
+            mTest = new GroupTest(true);
+            break;
+        case CONVOLVE_3X3:
+            mTest = new Convolve3x3(false);
+            break;
+        case INTRINSICS_CONVOLVE_3X3:
+            mTest = new Convolve3x3(true);
+            break;
+        case COLOR_MATRIX:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case INTRINSICS_COLOR_MATRIX:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case INTRINSICS_COLOR_MATRIX_GREY:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case COPY:
+            mTest = new Copy();
+            break;
+        case CROSS_PROCESS_USING_LUT:
+            mTest = new CrossProcess();
+            break;
+        case CONVOLVE_5X5:
+            mTest = new Convolve5x5(false);
+            break;
+        case INTRINSICS_CONVOLVE_5X5:
+            mTest = new Convolve5x5(true);
+            break;
+        case MANDELBROT:
+            mTest = new Mandelbrot();
+            break;
+        case INTRINSICS_BLEND:
+            mTest = new Blend();
+            break;
+        case INTRINSICS_BLUR_25G:
+            mTest = new Blur25G();
+            break;
+        case VIBRANCE:
+            mTest = new Vibrance();
+            break;
+        case BW_FILTER:
+            mTest = new BWFilter();
+            break;
+        case SHADOWS:
+            mTest = new Shadows();
+            break;
+        case CONTRAST:
+            mTest = new Contrast();
+            break;
+        case EXPOSURE:
+            mTest = new Exposure();
+            break;
+        case WHITE_BALANCE:
+            mTest = new WhiteBalance();
+            break;
+        case COLOR_CUBE:
+            mTest = new ColorCube(false);
+            break;
+        case COLOR_CUBE_3D_INTRINSIC:
+            mTest = new ColorCube(true);
+            break;
+        case USAGE_IO:
+            mTest = new UsageIO();
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
+        setupBars();
+
+        mTest.runTest();
+        updateDisplay();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
+            this, R.layout.spinner_layout, TestName.values()));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(TestName.values()[pos]);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    void init() {
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
+                                         mBitmapIn.getConfig());
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
+
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
+
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
+
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+
+        mRS = RenderScript.create(this);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
+
+
+        setupTests();
+        changeTest(TestName.LEVELS_VEC3_RELAXED);
+    }
+
+    void cleanup() {
+        synchronized(this) {
+            RenderScript rs = mRS;
+            mRS = null;
+            while(mDoingBenchmark) {
+                try {
+                    Thread.sleep(1, 0);
+                } catch(InterruptedException e) {
+                }
+
+            }
+            rs.destroy();
+        }
+
+        mInPixelsAllocation = null;
+        mInPixelsAllocation2 = null;
+        mOutPixelsAllocation = null;
+        mBitmapIn = null;
+        mBitmapIn2 = null;
+        mBitmapOut = null;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        init();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        cleanup();
+    }
+
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        init();
+    }
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        return BitmapFactory.decodeResource(getResources(), resource, options);
+    }
+
+    // button hook
+    public void benchmark(View v) {
+        float t = getBenchmark();
+        //long javaTime = javaFilter();
+        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
+        mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (TestName tn: TestName.values()) {
+                changeTest(tn);
+                float t = getBenchmark();
+                String s = new String("" + tn.toString() + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(TestName.LEVELS_VEC3_RELAXED);
+    }
+
+
+
+    // For benchmark test
+    public float getBenchmark() {
+        if (mRS == null) {
+            return 0;
+        }
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
+        t = java.lang.System.currentTimeMillis();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
+        t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
+
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+        return ft;
+    }
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java b/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
new file mode 100644
index 0000000..5263c61
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingTest.java
@@ -0,0 +1,379 @@
+/*
+ * 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 com.android.rs.image;
+
+import com.android.rs.image.ImageProcessingTestRunner;
+
+import android.os.Bundle;
+import com.android.rs.image.ImageProcessingActivity.TestName;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+/**
+ * ImageProcessing benchmark test.
+ * To run the test, please use command
+ *
+ * adb shell am instrument -e iteration <n> -w com.android.rs.image/.ImageProcessingTestRunner
+ *
+ */
+public class ImageProcessingTest extends ActivityInstrumentationTestCase2<ImageProcessingActivity> {
+    private final String TAG = "ImageProcessingTest";
+    private final String TEST_NAME = "Testname";
+    private final String ITERATIONS = "Iterations";
+    private final String BENCHMARK = "Benchmark";
+    private static int INSTRUMENTATION_IN_PROGRESS = 2;
+    private int mIteration;
+    private ImageProcessingActivity mActivity;
+
+    public ImageProcessingTest() {
+        super(ImageProcessingActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(false);
+        mActivity = getActivity();
+        ImageProcessingTestRunner mRunner = (ImageProcessingTestRunner) getInstrumentation();
+        mIteration = mRunner.mIteration;
+        assertTrue("please enter a valid iteration value", mIteration > 0);
+   }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    class TestAction implements Runnable {
+        TestName mTestName;
+        float mResult;
+        public TestAction(TestName testName) {
+            mTestName = testName;
+        }
+        public void run() {
+            mActivity.changeTest(mTestName);
+            mResult = mActivity.getBenchmark();
+            Log.v(TAG, "Benchmark for test \"" + mTestName.toString() + "\" is: " + mResult);
+            synchronized(this) {
+                this.notify();
+            }
+        }
+        public float getBenchmark() {
+            return mResult;
+        }
+    }
+
+    // Set the benchmark thread to run on ui thread
+    // Synchronized the thread such that the test will wait for the benchmark thread to finish
+    public void runOnUiThread(Runnable action) {
+        synchronized(action) {
+            mActivity.runOnUiThread(action);
+            try {
+                action.wait();
+            } catch (InterruptedException e) {
+                Log.v(TAG, "waiting for action running on UI thread is interrupted: " +
+                        e.toString());
+            }
+        }
+    }
+
+    public void runTest(TestAction ta, String testName) {
+        float sum = 0;
+        for (int i = 0; i < mIteration; i++) {
+            runOnUiThread(ta);
+            float bmValue = ta.getBenchmark();
+            Log.v(TAG, "results for iteration " + i + " is " + bmValue);
+            sum += bmValue;
+        }
+        float avgResult = sum/mIteration;
+
+        // post result to INSTRUMENTATION_STATUS
+        Bundle results = new Bundle();
+        results.putString(TEST_NAME, testName);
+        results.putInt(ITERATIONS, mIteration);
+        results.putFloat(BENCHMARK, avgResult);
+        getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
+    }
+
+    // Test case 0: Levels Vec3 Relaxed
+    @LargeTest
+    public void testLevelsVec3Relaxed() {
+        TestAction ta = new TestAction(TestName.LEVELS_VEC3_RELAXED);
+        runTest(ta, TestName.LEVELS_VEC3_RELAXED.name());
+    }
+
+    // Test case 1: Levels Vec4 Relaxed
+    @LargeTest
+    public void testLevelsVec4Relaxed() {
+        TestAction ta = new TestAction(TestName.LEVELS_VEC4_RELAXED);
+        runTest(ta, TestName.LEVELS_VEC4_RELAXED.name());
+    }
+
+    // Test case 2: Levels Vec3 Full
+    @LargeTest
+    public void testLevelsVec3Full() {
+        TestAction ta = new TestAction(TestName.LEVELS_VEC3_FULL);
+        runTest(ta, TestName.LEVELS_VEC3_FULL.name());
+    }
+
+    // Test case 3: Levels Vec4 Full
+    @LargeTest
+    public void testLevelsVec4Full() {
+        TestAction ta = new TestAction(TestName.LEVELS_VEC4_FULL);
+        runTest(ta, TestName.LEVELS_VEC4_FULL.name());
+    }
+
+    // Test case 4: Blur Radius 25
+    @LargeTest
+    public void testBlurRadius25() {
+        TestAction ta = new TestAction(TestName.BLUR_RADIUS_25);
+        runTest(ta, TestName.BLUR_RADIUS_25.name());
+    }
+
+    // Test case 5: Intrinsic Blur Radius 25
+    @LargeTest
+    public void testIntrinsicBlurRadius25() {
+        TestAction ta = new TestAction(TestName.INTRINSIC_BLUE_RADIUS_25);
+        runTest(ta, TestName.INTRINSIC_BLUE_RADIUS_25.name());
+    }
+
+    // Test case 6: Greyscale
+    @LargeTest
+    public void testGreyscale() {
+        TestAction ta = new TestAction(TestName.GREYSCALE);
+        runTest(ta, TestName.GREYSCALE.name());
+    }
+
+    // Test case 7: Grain
+    @LargeTest
+    public void testGrain() {
+        TestAction ta = new TestAction(TestName.GRAIN);
+        runTest(ta, TestName.GRAIN.name());
+    }
+
+    // Test case 8: Fisheye Full
+    @LargeTest
+    public void testFisheyeFull() {
+        TestAction ta = new TestAction(TestName.FISHEYE_FULL);
+        runTest(ta, TestName.FISHEYE_FULL.name());
+    }
+
+    // Test case 9: Fisheye Relaxed
+    @LargeTest
+    public void testFishEyeRelaxed() {
+        TestAction ta = new TestAction(TestName.FISHEYE_RELAXED);
+        runTest(ta, TestName.FISHEYE_RELAXED.name());
+    }
+
+    // Test case 10: Fisheye Approximate Full
+    @LargeTest
+    public void testFisheyeApproximateFull() {
+        TestAction ta = new TestAction(TestName.FISHEYE_APPROXIMATE_FULL);
+        runTest(ta, TestName.FISHEYE_APPROXIMATE_FULL.name());
+    }
+
+    // Test case 11: Fisheye Approximate Relaxed
+    @LargeTest
+    public void testFisheyeApproximateRelaxed() {
+        TestAction ta = new TestAction(TestName.FISHEYE_APPROXIMATE_RELAXED);
+        runTest(ta, TestName.FISHEYE_APPROXIMATE_RELAXED.name());
+    }
+
+    // Test case 12: Vignette Full
+    @LargeTest
+    public void testVignetteFull() {
+        TestAction ta = new TestAction(TestName.VIGNETTE_FULL);
+        runTest(ta, TestName.VIGNETTE_FULL.name());
+    }
+
+    // Test case 13: Vignette Relaxed
+    @LargeTest
+    public void testVignetteRelaxed() {
+        TestAction ta = new TestAction(TestName.VIGNETTE_RELAXED);
+        runTest(ta, TestName.VIGNETTE_RELAXED.name());
+    }
+
+    // Test case 14: Vignette Approximate Full
+    @LargeTest
+    public void testVignetteApproximateFull() {
+        TestAction ta = new TestAction(TestName.VIGNETTE_APPROXIMATE_FULL);
+        runTest(ta, TestName.VIGNETTE_APPROXIMATE_FULL.name());
+    }
+
+    // Test case 15: Vignette Approximate Relaxed
+    @LargeTest
+    public void testVignetteApproximateRelaxed() {
+        TestAction ta = new TestAction(TestName.VIGNETTE_APPROXIMATE_RELAXED);
+        runTest(ta, TestName.VIGNETTE_APPROXIMATE_RELAXED.name());
+    }
+
+    // Test case 16: Group Test (emulated)
+    @LargeTest
+    public void testGroupTestEmulated() {
+        TestAction ta = new TestAction(TestName.GROUP_TEST_EMULATED);
+        runTest(ta, TestName.GROUP_TEST_EMULATED.name());
+    }
+
+    // Test case 17: Group Test (native)
+    @LargeTest
+    public void testGroupTestNative() {
+        TestAction ta = new TestAction(TestName.GROUP_TEST_NATIVE);
+        runTest(ta, TestName.GROUP_TEST_NATIVE.name());
+    }
+
+    // Test case 18: Convolve 3x3
+    @LargeTest
+    public void testConvolve3x3() {
+        TestAction ta = new TestAction(TestName.CONVOLVE_3X3);
+        runTest(ta, TestName.CONVOLVE_3X3.name());
+    }
+
+    // Test case 19: Intrinsics Convolve 3x3
+    @LargeTest
+    public void testIntrinsicsConvolve3x3() {
+        TestAction ta = new TestAction(TestName.INTRINSICS_CONVOLVE_3X3);
+        runTest(ta, TestName.INTRINSICS_CONVOLVE_3X3.name());
+    }
+
+    // Test case 20: ColorMatrix
+    @LargeTest
+    public void testColorMatrix() {
+        TestAction ta = new TestAction(TestName.COLOR_MATRIX);
+        runTest(ta, TestName.COLOR_MATRIX.name());
+    }
+
+    // Test case 21: Intrinsics ColorMatrix
+    @LargeTest
+    public void testIntrinsicsColorMatrix() {
+        TestAction ta = new TestAction(TestName.INTRINSICS_COLOR_MATRIX);
+        runTest(ta, TestName.INTRINSICS_COLOR_MATRIX.name());
+    }
+
+    // Test case 22: Intrinsics ColorMatrix Grey
+    @LargeTest
+    public void testIntrinsicsColorMatrixGrey() {
+        TestAction ta = new TestAction(TestName.INTRINSICS_COLOR_MATRIX_GREY);
+        runTest(ta, TestName.INTRINSICS_COLOR_MATRIX_GREY.name());
+    }
+
+    // Test case 23: Copy
+    @LargeTest
+    public void testCopy() {
+        TestAction ta = new TestAction(TestName.COPY);
+        runTest(ta, TestName.COPY.name());
+    }
+
+    // Test case 24: CrossProcess (using LUT)
+    @LargeTest
+    public void testCrossProcessUsingLUT() {
+        TestAction ta = new TestAction(TestName.CROSS_PROCESS_USING_LUT);
+        runTest(ta, TestName.CROSS_PROCESS_USING_LUT.name());
+    }
+
+    // Test case 25: Convolve 5x5
+    @LargeTest
+    public void testConvolve5x5() {
+        TestAction ta = new TestAction(TestName.CONVOLVE_5X5);
+        runTest(ta, TestName.CONVOLVE_5X5.name());
+    }
+
+    // Test case 26: Intrinsics Convolve 5x5
+    @LargeTest
+    public void testIntrinsicsConvolve5x5() {
+        TestAction ta = new TestAction(TestName.INTRINSICS_CONVOLVE_5X5);
+        runTest(ta, TestName.INTRINSICS_CONVOLVE_5X5.name());
+    }
+
+    // Test case 27: Mandelbrot
+    @LargeTest
+    public void testMandelbrot() {
+        TestAction ta = new TestAction(TestName.MANDELBROT);
+        runTest(ta, TestName.MANDELBROT.name());
+    }
+
+    // Test case 28: Intrinsics Blend
+    @LargeTest
+    public void testIntrinsicsBlend() {
+        TestAction ta = new TestAction(TestName.INTRINSICS_BLEND);
+        runTest(ta, TestName.INTRINSICS_BLEND.name());
+    }
+
+    // Test case 29: Intrinsics Blur 25 uchar
+    @LargeTest
+    public void testIntrinsicsBlur25G() {
+        TestAction ta = new TestAction(TestName.INTRINSICS_BLUR_25G);
+        runTest(ta, TestName.INTRINSICS_BLUR_25G.name());
+    }
+
+    // Test case 30: Vibrance
+    @LargeTest
+    public void testVibrance() {
+        TestAction ta = new TestAction(TestName.VIBRANCE);
+        runTest(ta, TestName.VIBRANCE.name());
+    }
+
+    // Test case 31: BWFilter
+    @LargeTest
+    public void testBWFilter() {
+        TestAction ta = new TestAction(TestName.BW_FILTER);
+        runTest(ta, TestName.BW_FILTER.name());
+    }
+
+    // Test case 32: Shadows
+    @LargeTest
+    public void testShadows() {
+        TestAction ta = new TestAction(TestName.SHADOWS);
+        runTest(ta, TestName.SHADOWS.name());
+    }
+
+    // Test case 33: Contrast
+    @LargeTest
+    public void testContrast() {
+        TestAction ta = new TestAction(TestName.CONTRAST);
+        runTest(ta, TestName.CONTRAST.name());
+    }
+
+    // Test case 34: Exposure
+    @LargeTest
+    public void testExposure(){
+        TestAction ta = new TestAction(TestName.EXPOSURE);
+        runTest(ta, TestName.EXPOSURE.name());
+    }
+
+    // Test case 35: White Balance
+    @LargeTest
+    public void testWhiteBalance() {
+        TestAction ta = new TestAction(TestName.WHITE_BALANCE);
+        runTest(ta, TestName.WHITE_BALANCE.name());
+    }
+
+    // Test case 36: Color Cube
+    @LargeTest
+    public void testColorCube() {
+        TestAction ta = new TestAction(TestName.COLOR_CUBE);
+        runTest(ta, TestName.COLOR_CUBE.name());
+    }
+
+    // Test case 37: Color Cube (3D Intrinsic)
+    @LargeTest
+    public void testColorCube3DIntrinsic() {
+        TestAction ta = new TestAction(TestName.COLOR_CUBE_3D_INTRINSIC);
+        runTest(ta, TestName.COLOR_CUBE_3D_INTRINSIC.name());
+    }
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingTestRunner.java b/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingTestRunner.java
new file mode 100644
index 0000000..36fbb3e
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/ImageProcessingTestRunner.java
@@ -0,0 +1,48 @@
+/*
+ * 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 com.android.rs.image;
+
+import com.android.rs.image.ImageProcessingTest;
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import junit.framework.TestSuite;
+
+/**
+ * Run the ImageProcessing benchmark test
+ * adb shell am instrument -e iteration <n> -w com.android.rs.image/.ImageProcessingTestRunner
+ *
+ */
+public class ImageProcessingTestRunner extends InstrumentationTestRunner {
+    public int mIteration = 5;
+
+    @Override
+    public TestSuite getAllTests() {
+        TestSuite suite = new InstrumentationTestSuite(this);
+        suite.addTestSuite(ImageProcessingTest.class);
+        return suite;
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        String strIteration = (String) icicle.get("iteration");
+        if (strIteration != null) {
+            mIteration = Integer.parseInt(strIteration);
+        }
+    }
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/LevelsV4.java b/java/tests/ImageProcessing/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..9eb5647
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,167 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Matrix3f;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Mandelbrot.java b/java/tests/ImageProcessing/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..20036e6
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,98 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Shadows.java b/java/tests/ImageProcessing/src/com/android/rs/image/Shadows.java
new file mode 100644
index 0000000..98ab15f
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Shadows.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Shadows extends TestBase {
+    private ScriptC_shadows mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_shadows(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_prepareShadows(50.f);
+        mScript.forEach_shadowsKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/TestBase.java b/java/tests/ImageProcessing/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..a353d9c
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,151 @@
+/*
+ * 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 com.android.rs.image;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+import android.widget.Spinner;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
+    protected Allocation mOutPixelsAllocation;
+    protected ImageProcessingActivity act;
+
+    private class MessageProcessor extends RenderScript.RSMessageHandler {
+        ImageProcessingActivity mAct;
+
+        MessageProcessor(ImageProcessingActivity act) {
+            mAct = act;
+        }
+
+        public void run() {
+            mAct.updateDisplay();
+        }
+    }
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity ipact, Bitmap b, Bitmap b2, Bitmap outb) {
+        act = ipact;
+        mRS = ipact.mRS;
+        mRS.setMessageHandler(new MessageProcessor(act));
+
+        mInPixelsAllocation = ipact.mInPixelsAllocation;
+        mInPixelsAllocation2 = ipact.mInPixelsAllocation2;
+        mOutPixelsAllocation = ipact.mOutPixelsAllocation;
+
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    final public void runTestSendMessage() {
+        runTest();
+        mRS.sendMessage(0, null);
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void destroy() {
+        mRS.setMessageHandler(null);
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/UsageIO.java b/java/tests/ImageProcessing/src/com/android/rs/image/UsageIO.java
new file mode 100644
index 0000000..3f86311
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/UsageIO.java
@@ -0,0 +1,66 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.view.Surface;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.renderscript.Matrix4f;
+import android.renderscript.ScriptGroup;
+import android.util.Log;
+
+public class UsageIO extends TestBase {
+    private ScriptIntrinsicColorMatrix mMatrix;
+
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+    public UsageIO() {
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.setColorMatrix(m);
+
+        Type connect = mInPixelsAllocation.getType();
+
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect, Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, connect, Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
+
+        Surface s = mScratchPixelsAllocation2.getSurface();
+        mScratchPixelsAllocation1.setSurface(s);
+    }
+
+    public void runTest() {
+        mScratchPixelsAllocation1.copyFrom(mInPixelsAllocation);
+        mScratchPixelsAllocation1.ioSend();
+        mScratchPixelsAllocation2.ioReceive();
+        mMatrix.forEach(mScratchPixelsAllocation2, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Vibrance.java b/java/tests/ImageProcessing/src/com/android/rs/image/Vibrance.java
new file mode 100644
index 0000000..0bc1ff7
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Vibrance.java
@@ -0,0 +1,36 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Vibrance extends TestBase {
+    private ScriptC_vibrance mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_vibrance(mRS);
+    }
+
+    public void runTest() {
+        mScript.set_vibrance(50.f);
+        mScript.invoke_prepareVibrance();
+        mScript.forEach_vibranceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/Vignette.java b/java/tests/ImageProcessing/src/com/android/rs/image/Vignette.java
new file mode 100644
index 0000000..18d1103
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,154 @@
+/*
+ * 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 com.android.rs.image;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Vignette extends TestBase {
+    private ScriptC_vignette_full mScript_full = null;
+    private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+    private float shade = 0.5f;
+    private float slope = 20.0f;
+
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shade");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Slope");
+        b.setMax(100);
+        b.setProgress(20);
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        shade = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        slope = (float)progress;
+        do_init();
+    }
+    public void onBar4Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar5Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+        else
+            mScript_full.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
+            mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
+                    R.raw.vignette_relaxed);
+        else
+            mScript_full = new ScriptC_vignette_full(mRS, res,
+                    R.raw.vignette_full);
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/WhiteBalance.java b/java/tests/ImageProcessing/src/com/android/rs/image/WhiteBalance.java
new file mode 100644
index 0000000..a836067
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/WhiteBalance.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class WhiteBalance extends TestBase {
+    private ScriptC_wbalance mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_wbalance(mRS);
+    }
+
+    public void runTest() {
+        mScript.set_histogramSource(mInPixelsAllocation);
+        mScript.set_histogramWidth(mInPixelsAllocation.getType().getX());
+        mScript.set_histogramHeight(mInPixelsAllocation.getType().getY());
+        mScript.invoke_prepareWhiteBalance();
+        mScript.forEach_whiteBalanceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/blend.rs b/java/tests/ImageProcessing/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..9ec1246
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/blend.rs
@@ -0,0 +1,23 @@
+// 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.
+
+#include "ip.rsh"
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/bwfilter.rs b/java/tests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
new file mode 100644
index 0000000..e706d44
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static float sr = 0.f;
+static float sg = 0.f;
+static float sb = 0.f;
+
+void prepareBwFilter(uint32_t rw, uint32_t gw, uint32_t bw) {
+
+    sr = rw;
+    sg = gw;
+    sb = bw;
+
+    float imageMin = min(sg,sb);
+    imageMin = fmin(sr,imageMin);
+    float imageMax = max(sg,sb);
+    imageMax = fmax(sr,imageMax);
+    float avg = (imageMin + imageMax)/2;
+    sb /= avg;
+    sg /= avg;
+    sr /= avg;
+
+}
+
+void bwFilterKernel(const uchar4 *in, uchar4 *out) {
+    float r = in->r * sr;
+    float g = in->g * sg;
+    float b = in->b * sb;
+    float localMin, localMax, avg;
+    localMin = fmin(g,b);
+    localMin = fmin(r,localMin);
+    localMax = fmax(g,b);
+    localMax = fmax(r,localMax);
+    avg = (localMin+localMax) * 0.5f;
+    out->r = out->g = out->b = rsClamp(avg, 0, 255);
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/colorcube.rs b/java/tests/ImageProcessing/src/com/android/rs/image/colorcube.rs
new file mode 100644
index 0000000..4f1e73e
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/colorcube.rs
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+
+static rs_allocation gCube;
+static int4 gDims;
+static int4 gCoordMul;
+
+
+void setCube(rs_allocation c) {
+    gCube = c;
+    gDims.x = rsAllocationGetDimX(gCube);
+    gDims.y = rsAllocationGetDimY(gCube);
+    gDims.z = rsAllocationGetDimZ(gCube);
+    gDims.w = 0;
+
+    float4 m = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
+    gCoordMul = convert_int4(m * (float4)0x10000);
+
+    rsDebug("dims", gDims);
+    rsDebug("gCoordMul", gCoordMul);
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    //rsDebug("root", in);
+
+    int4 baseCoord = convert_int4(*in) * gCoordMul;
+    int4 coord1 = baseCoord >> (int4)16;
+    int4 coord2 = min(coord1 + 1, gDims - 1);
+
+    int4 weight2 = baseCoord & 0xffff;
+    int4 weight1 = (int4)0x10000 - weight2;
+
+    uint4 v000 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord1.z));
+    uint4 v100 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord1.z));
+    uint4 v010 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord1.z));
+    uint4 v110 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord1.z));
+    uint4 v001 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord2.z));
+    uint4 v101 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord2.z));
+    uint4 v011 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord2.z));
+    uint4 v111 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord2.z));
+
+    uint4 yz00 = ((v000 * weight1.x) + (v100 * weight2.x)) >> (int4)8;
+    uint4 yz10 = ((v010 * weight1.x) + (v110 * weight2.x)) >> (int4)8;
+    uint4 yz01 = ((v001 * weight1.x) + (v101 * weight2.x)) >> (int4)8;
+    uint4 yz11 = ((v011 * weight1.x) + (v111 * weight2.x)) >> (int4)8;
+
+    uint4 z0 = ((yz00 * weight1.y) + (yz10 * weight2.y)) >> (int4)16;
+    uint4 z1 = ((yz01 * weight1.y) + (yz11 * weight2.y)) >> (int4)16;
+
+    uint4 v = ((z0 * weight1.z) + (z1 * weight2.z)) >> (int4)16;
+    uint4 v2 = (v + 0x7f) >> (int4)8;
+
+    *out = convert_uchar4(v2);
+    out->a = 0xff;
+
+    #if 0
+    if (in->r != out->r) {
+        rsDebug("dr", in->r - out->r);
+        //rsDebug("in", convert_int4(*in));
+        //rsDebug("coord1", coord1);
+        //rsDebug("coord2", coord2);
+        //rsDebug("weight1", weight1);
+        //rsDebug("weight2", weight2);
+        //rsDebug("yz00", yz00);
+        //rsDebug("z0", z0);
+        //rsDebug("v", v);
+        //rsDebug("v2", v2);
+        //rsDebug("out", convert_int4(*out));
+    }
+    #endif
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/colormatrix.fs b/java/tests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
new file mode 100644
index 0000000..86fb248
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static rs_matrix4x4 Mat;
+
+void init() {
+    rsMatrixLoadIdentity(&Mat);
+}
+
+void setMatrix(rs_matrix4x4 m) {
+    Mat = m;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    float4 f = convert_float4(in);
+    f = rsMatrixMultiply(&Mat, f);
+    f = clamp(f, 0.f, 255.f);
+    return convert_uchar4(f);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/contrast.rs b/java/tests/ImageProcessing/src/com/android/rs/image/contrast.rs
new file mode 100644
index 0000000..d3743d3
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/contrast.rs
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static float brightM = 0.f;
+static float brightC = 0.f;
+
+void setBright(float v) {
+    brightM = pow(2.f, v / 100.f);
+    brightC = 127.f - brightM * 127.f;
+}
+
+void contrast(const uchar4 *in, uchar4 *out)
+{
+#if 0
+    out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
+    out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
+    out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
+#else
+    float3 v = convert_float3(in->rgb) * brightM + brightC;
+    out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+#endif
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs b/java/tests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
new file mode 100644
index 0000000..177e86e
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
+    p00 *= gCoeffs[0];
+    p01 *= gCoeffs[1];
+    p02 *= gCoeffs[2];
+    p10 *= gCoeffs[3];
+    p11 *= gCoeffs[4];
+    p12 *= gCoeffs[5];
+    p20 *= gCoeffs[6];
+    p21 *= gCoeffs[7];
+    p22 *= gCoeffs[8];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = clamp(p20, 0.f, 255.f);
+    return convert_uchar4(p20);
+}
+
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs b/java/tests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
new file mode 100644
index 0000000..922a593
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    return convert_uchar4(p0);
+}
+
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/copy.fs b/java/tests/ImageProcessing/src/com/android/rs/image/copy.fs
new file mode 100644
index 0000000..6595874
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/copy.fs
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    return v_in;
+}
+
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/exposure.rs b/java/tests/ImageProcessing/src/com/android/rs/image/exposure.rs
new file mode 100644
index 0000000..0f05cb9
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/exposure.rs
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static float bright = 0.f;
+
+void setBright(float v) {
+    bright = 255.f / (255.f - v);
+}
+
+void exposure(const uchar4 *in, uchar4 *out)
+{
+    out->r = rsClamp((int)(bright * in->r), 0, 255);
+    out->g = rsClamp((int)(bright * in->g), 0, 255);
+    out->b = rsClamp((int)(bright * in->b), 0, 255);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/fisheye.rsh b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..2eacb7d
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..fcf0a3d
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..ed69ff4
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye_approx.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
new file mode 100644
index 0000000..ed69ff4
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye_approx.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
new file mode 100644
index 0000000..f986b5d
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
new file mode 100644
index 0000000..f986b5d
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/grain.fs b/java/tests/ImageProcessing/src/com/android/rs/image/grain.fs
new file mode 100644
index 0000000..2e62cd7
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/grain.fs
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+uchar __attribute__((kernel)) genRand() {
+    return (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWMask;
+int32_t gHMask;
+
+rs_allocation gBlendSource;
+uchar __attribute__((kernel)) blend9(uint32_t x, uint32_t y) {
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
+
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = min(p20 >> 10, (uint)255);
+    return (uchar)p20;
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(in);
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    return p;
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/greyscale.fs b/java/tests/ImageProcessing/src/com/android/rs/image/greyscale.fs
new file mode 100644
index 0000000..4e13072
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/greyscale.fs
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    float4 f4 = rsUnpackColor8888(v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    return rsPackColorTo8888(mono);
+}
+
+uchar __attribute__((kernel)) toU8(uchar4 v_in) {
+    float4 f4 = convert_float4(v_in);
+    return (uchar)dot(f4.rgb, gMonoMult);
+}
+
+uchar4 __attribute__((kernel)) toU8_4(uchar v_in) {
+    return (uchar4)v_in;
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/ip.rsh b/java/tests/ImageProcessing/src/com/android/rs/image/ip.rsh
new file mode 100644
index 0000000..01a3346
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/ip.rsh
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/levels.rsh b/java/tests/ImageProcessing/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..e289906
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    uchar4 out;
+    float3 pixel = convert_float4(in).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out.xyz = convert_uchar3(pixel);
+    out.w = 0xff;
+    return out;
+}
+
+uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(in);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    return convert_uchar4(pixel);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/levels_full.rs b/java/tests/ImageProcessing/src/com/android/rs/image/levels_full.rs
new file mode 100644
index 0000000..28596ba
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/levels_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "levels.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs b/java/tests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
new file mode 100644
index 0000000..28596ba
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "levels.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs b/java/tests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..de0bd00
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,55 @@
+// 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.
+
+#include "ip.rsh"
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    return (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.f;
+    if (iter <= (gMaxIteration / 3))
+      return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                      (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                      (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/shadows.rs b/java/tests/ImageProcessing/src/com/android/rs/image/shadows.rs
new file mode 100644
index 0000000..f6c149d
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/shadows.rs
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static double shadowFilterMap[] = {
+    -0.00591,  0.0001,
+     1.16488,  0.01668,
+    -0.18027, -0.06791,
+    -0.12625,  0.09001,
+     0.15065, -0.03897
+};
+
+static double poly[] = {
+    0., 0.,
+    0., 0.,
+    0.
+};
+
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static double fastevalPoly(double *poly,int n, double x){
+
+    double f =x;
+    double sum = poly[0]+poly[1]*f;
+    int i;
+    for (i = 2; i < n; i++) {
+        f*=x;
+        sum += poly[i]*f;
+    }
+    return sum;
+}
+
+static ushort3 rgb2hsv( uchar4 rgb)
+{
+    int iMin,iMax,chroma;
+
+    int ri = rgb.r;
+    int gi = rgb.g;
+    int bi = rgb.b;
+    short rv,rs,rh;
+
+    if (ri > gi) {
+        iMax = max (ri, bi);
+        iMin = min (gi, bi);
+    } else {
+        iMax = max (gi, bi);
+        iMin = min (ri, bi);
+    }
+
+    chroma = iMax - iMin;
+    // set value
+    rv = (short)( iMax << ABITS);
+
+    // set saturation
+    if (rv == 0)
+        rs = 0;
+    else
+        rs = (short)((k1*chroma)/iMax);
+
+    // set hue
+    if (rs == 0)
+        rh = 0;
+    else {
+        if ( ri == iMax ) {
+            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
+            if (rh >= k2) rh -= k2;
+        } else if (gi  == iMax)
+            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
+        else // (bi == iMax )
+                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
+    }
+
+    ushort3 out;
+    out.x = rv;
+    out.y = rs;
+    out.z = rh;
+    return out;
+}
+
+static uchar4 hsv2rgb(ushort3 hsv)
+{
+    int ABITS = 4;
+    int HSCALE = 256;
+    int m;
+    int H,X,ih,is,iv;
+    int k1=255<<ABITS;
+    int k2=HSCALE<<ABITS;
+    int k3=1<<(ABITS-1);
+    int rr=0;
+    int rg=0;
+    int rb=0;
+    short cv = hsv.x;
+    short cs = hsv.y;
+    short ch = hsv.z;
+
+    // set chroma and min component value m
+    //chroma = ( cv * cs )/k1;
+    //m = cv - chroma;
+    m = ((int)cv*(k1 - (int)cs ))/k1;
+
+    // chroma  == 0 <-> cs == 0 --> m=cv
+    if (cs == 0) {
+        rb = ( rg = ( rr =( cv >> ABITS) ));
+    } else {
+        ih=(int)ch;
+        is=(int)cs;
+        iv=(int)cv;
+
+        H = (6*ih)/k2;
+        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
+
+        // removing additional bits --> unit8
+        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
+        m=m >> ABITS;
+
+        // ( chroma + m ) --> cv ;
+        cv=(short) (cv >> ABITS);
+        switch (H) {
+        case 0:
+            rr = cv;
+            rg = X;
+            rb = m;
+            break;
+        case 1:
+            rr = X;
+            rg = cv;
+            rb = m;
+            break;
+        case 2:
+            rr = m;
+            rg = cv;
+            rb = X;
+            break;
+        case 3:
+            rr = m;
+            rg = X;
+            rb = cv;
+            break;
+        case 4:
+            rr = X;
+            rg = m;
+            rb = cv;
+            break;
+        case 5:
+            rr = cv;
+            rg = m ;
+            rb = X;
+            break;
+        }
+    }
+
+    uchar4 rgb;
+
+    rgb.r =  rr;
+    rgb.g =  rg;
+    rgb.b =  rb;
+
+    return rgb;
+}
+
+void prepareShadows(float scale) {
+    double s = (scale>=0)?scale:scale/5;
+    for (int i = 0; i < 5; i++) {
+        poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
+    }
+}
+
+void shadowsKernel(const uchar4 *in, uchar4 *out) {
+    ushort3 hsv = rgb2hsv(*in);
+    double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
+    if (v>4080) v = 4080;
+    hsv.x = (unsigned short) ((v>0)?v:0);
+    *out = hsv2rgb(hsv);
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/threshold.fs b/java/tests/ImageProcessing/src/com/android/rs/image/threshold.fs
new file mode 100644
index 0000000..0b2c2e8
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/threshold.fs
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+
+int height;
+int width;
+static int radius;
+
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+void setRadius(int rad) {
+    radius = rad;
+    // Compute gaussian weights for the blur
+    // e is the euler's number
+    float e = 2.718281828459045f;
+    float pi = 3.1415926535897932f;
+    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+    // x is of the form [-radius .. 0 .. radius]
+    // and sigma varies with radius.
+    // Based on some experimental radius values and sigma's
+    // we approximately fit sigma = f(radius) as
+    // sigma = radius * 0.4  + 0.6
+    // The larger the radius gets, the more our gaussian blur
+    // will resemble a box blur since with large sigma
+    // the gaussian curve begins to lose its shape
+    float sigma = 0.4f * (float)radius + 0.6f;
+
+    // Now compute the coefficints
+    // We will store some redundant values to save some math during
+    // the blur calculations
+    // precompute some values
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    //Now we need to normalize the weights because all our coefficients need to add up to one
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+float4 __attribute__((kernel)) copyIn(uchar4 in) {
+    return convert_float4(in);
+}
+
+uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    int gi = 0;
+    uchar4 out;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    }
+
+    out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out.w = 0xff;
+    return out;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    }
+
+    return blurredPixel;
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vibrance.rs b/java/tests/ImageProcessing/src/com/android/rs/image/vibrance.rs
new file mode 100644
index 0000000..ad4de58
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vibrance.rs
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+float vibrance = 0.f;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+static float S  = 0.f;
+static float MS = 0.f;
+static float Rt = 0.f;
+static float Gt = 0.f;
+static float Bt = 0.f;
+static float Vib = 0.f;
+
+void vibranceKernel(const uchar4 *in, uchar4 *out) {
+
+    float R, G, B;
+
+    int r = in->r;
+    int g = in->g;
+    int b = in->b;
+    float red = (r-max(g, b))/256.f;
+    float sx = (float)(Vib/(1+native_exp(-red*3)));
+    S = sx+1;
+    MS = 1.0f - S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+    int t = (r + g) / 2;
+    R = r;
+    G = g;
+    B = b;
+
+    float Rc = R * (Rt + S) + G * Gt + B * Bt;
+    float Gc = R * Rt + G * (Gt + S) + B * Bt;
+    float Bc = R * Rt + G * Gt + B * (Bt + S);
+
+    out->r = rsClamp(Rc, 0, 255);
+    out->g = rsClamp(Gc, 0, 255);
+    out->b = rsClamp(Bc, 0, 255);
+
+}
+
+void prepareVibrance() {
+
+    Vib = vibrance/100.f;
+    S  = Vib + 1;
+    MS = 1.0f - S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+
+}
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vignette.rsh b/java/tests/ImageProcessing/src/com/android/rs/image/vignette.rsh
new file mode 100644
index 0000000..04ca1f1
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vignette.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade / ( 1.0f + sloped_neg_range * exp(sloped_dist_ratio) );
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..5668621
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * native_exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..00cbbc4
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette_approx.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
new file mode 100644
index 0000000..00cbbc4
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette_approx.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vignette_full.rs b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
new file mode 100644
index 0000000..8202c5c
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
new file mode 100644
index 0000000..8202c5c
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette.rsh"
+
diff --git a/java/tests/ImageProcessing/src/com/android/rs/image/wbalance.rs b/java/tests/ImageProcessing/src/com/android/rs/image/wbalance.rs
new file mode 100644
index 0000000..6650671
--- /dev/null
+++ b/java/tests/ImageProcessing/src/com/android/rs/image/wbalance.rs
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
+
+rs_allocation histogramSource;
+uint32_t histogramHeight;
+uint32_t histogramWidth;
+
+static float scaleR;
+static float scaleG;
+static float scaleB;
+
+static uchar4 estimateWhite() {
+
+    for (int i = 0; i < 256; i++) {
+        histR[i] = 0; histG[i] = 0; histB[i] = 0;
+    }
+
+    for (uint32_t i = 0; i < histogramHeight; i++) {
+        for (uint32_t j = 0; j < histogramWidth; j++) {
+            uchar4 in = rsGetElementAt_uchar4(histogramSource, j, i);
+            histR[in.r]++;
+            histG[in.g]++;
+            histB[in.b]++;
+        }
+    }
+
+    int min_r = -1, min_g = -1, min_b = -1;
+    int max_r =  0, max_g =  0, max_b =  0;
+    int sum_r =  0, sum_g =  0, sum_b =  0;
+
+    for (int i = 1; i < 255; i++) {
+        int r = histR[i];
+        int g = histG[i];
+        int b = histB[i];
+        sum_r += r;
+        sum_g += g;
+        sum_b += b;
+
+        if (r>0){
+            if (min_r < 0) min_r = i;
+            max_r = i;
+        }
+        if (g>0){
+            if (min_g < 0) min_g = i;
+            max_g = i;
+        }
+        if (b>0){
+            if (min_b < 0) min_b = i;
+            max_b = i;
+        }
+    }
+
+    int sum15r = 0, sum15g = 0, sum15b = 0;
+    int count15r = 0, count15g = 0, count15b = 0;
+    int tmp_r = 0, tmp_g = 0, tmp_b = 0;
+
+    for (int i = 254; i >0; i--) {
+        int r = histR[i];
+        int g = histG[i];
+        int b = histB[i];
+        tmp_r += r;
+        tmp_g += g;
+        tmp_b += b;
+
+        if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
+            sum15r += r*i;
+            count15r += r;
+        }
+        if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
+            sum15g += g*i;
+            count15g += g;
+        }
+        if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
+            sum15b += b*i;
+            count15b += b;
+        }
+
+    }
+
+    uchar4 out;
+
+    if ((count15r>0) && (count15g>0) && (count15b>0) ){
+        out.r = sum15r/count15r;
+        out.g = sum15g/count15g;
+        out.b = sum15b/count15b;
+    }else {
+        out.r = out.g = out.b = 255;
+    }
+
+    return out;
+
+}
+
+void prepareWhiteBalance() {
+    uchar4 estimation = estimateWhite();
+    int minimum = min(estimation.r, min(estimation.g, estimation.b));
+    int maximum = max(estimation.r, max(estimation.g, estimation.b));
+    float avg = (minimum + maximum) / 2.f;
+
+    scaleR =  avg/estimation.r;
+    scaleG =  avg/estimation.g;
+    scaleB =  avg/estimation.b;
+
+}
+
+static unsigned char contrastClamp(int c)
+{
+    int N = 255;
+    c &= ~(c >> 31);
+    c -= N;
+    c &= (c >> 31);
+    c += N;
+    return  (unsigned char) c;
+}
+
+void whiteBalanceKernel(const uchar4 *in, uchar4 *out) {
+    float Rc =  in->r*scaleR;
+    float Gc =  in->g*scaleG;
+    float Bc =  in->b*scaleB;
+
+    out->r = contrastClamp(Rc);
+    out->g = contrastClamp(Gc);
+    out->b = contrastClamp(Bc);
+}
diff --git a/java/tests/ImageProcessing2/Android.mk b/java/tests/ImageProcessing2/Android.mk
new file mode 100644
index 0000000..52966a3
--- /dev/null
+++ b/java/tests/ImageProcessing2/Android.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.support.v8.renderscript
+
+LOCAL_PACKAGE_NAME := ImageProcessing2
+LOCAL_SDK_VERSION := 8
+LOCAL_RENDERSCRIPT_TARGET_API := 18
+LOCAL_RENDERSCRIPT_COMPATIBILITY := 18
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := $(TOPDIR)external/clang/lib/Headers \
+                                        $(TOPDIR)frameworks/rs/scriptc
+
+LOCAL_RENDERSCRIPT_FLAGS := -rs-package-name=android.support.v8.renderscript
+LOCAL_REQUIRED_MODULES := librsjni
+
+include $(BUILD_PACKAGE)
+
+#include $(call all-makefiles-under, $(LOCAL_PATH))
+
diff --git a/java/tests/ImageProcessing2/AndroidManifest.xml b/java/tests/ImageProcessing2/AndroidManifest.xml
new file mode 100644
index 0000000..20ee053
--- /dev/null
+++ b/java/tests/ImageProcessing2/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.image2">
+    <uses-sdk android:minSdkVersion="8" />
+    <application android:label="IP GB">
+        <activity android:name="ImageProcessingActivity2">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/city.png b/java/tests/ImageProcessing2/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..856eeff
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/city.png
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/layout/main.xml b/java/tests/ImageProcessing2/res/layout/main.xml
new file mode 100644
index 0000000..f0a2b92
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/layout/main.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider1Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/slider1"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider2Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/slider2"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider3Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/slider3"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider4Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider4"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider5Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider5"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/java/tests/ImageProcessing2/res/layout/spinner_layout.xml b/java/tests/ImageProcessing2/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/java/tests/ImageProcessing2/res/values/strings.xml b/java/tests/ImageProcessing2/res/values/strings.xml
new file mode 100644
index 0000000..a7dd165
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <!--slider label -->
+    <string name="blur_description">Blur Radius</string>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
+
+</resources>
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/BWFilter.java b/java/tests/ImageProcessing2/src/com/android/rs/image/BWFilter.java
new file mode 100644
index 0000000..4b19856
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/BWFilter.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+
+public class BWFilter extends TestBase {
+    private ScriptC_bwfilter mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_bwfilter(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_prepareBwFilter(50, 50, 50);
+        mScript.forEach_bwFilterKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..d81ba88
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -0,0 +1,170 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    if (mRS != null) {
+                        runTest();
+                        act.updateDisplay();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..b518b02
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,114 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
+
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
+    }
+
+    public void setupBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
+    }
+
+    public void exitBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
new file mode 100644
index 0000000..19aa9f7
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.graphics.Bitmap;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25G extends TestBase {
+    private final int MAX_RADIUS = 25;
+    private float mRadius = MAX_RADIUS;
+
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private ScriptC_greyscale mScript;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25G() {
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        mIntrinsic.setRadius(mRadius);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_greyscale(mRS);
+        mScript.forEach_toU8(mInPixelsAllocation, mScratchPixelsAllocation1);
+
+        mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8(mRS));
+        mIntrinsic.setRadius(MAX_RADIUS);
+        mIntrinsic.setInput(mScratchPixelsAllocation1);
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mScratchPixelsAllocation2);
+    }
+
+    public void setupBenchmark() {
+        mIntrinsic.setRadius(MAX_RADIUS);
+    }
+
+    public void exitBenchmark() {
+        mIntrinsic.setRadius(mRadius);
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mScript.forEach_toU8_4(mScratchPixelsAllocation2, mOutPixelsAllocation);
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ColorCube.java b/java/tests/ImageProcessing2/src/com/android/rs/image/ColorCube.java
new file mode 100644
index 0000000..e960385
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ColorCube.java
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class ColorCube extends TestBase {
+    private Allocation mCube;
+    private ScriptC_colorcube mScript;
+    private ScriptIntrinsic3DLUT mIntrinsic;
+    private boolean mUseIntrinsic;
+
+    public ColorCube(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    private void initCube() {
+        final int sx = 32;
+        final int sy = 32;
+        final int sz = 16;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(sx);
+        tb.setY(sy);
+        tb.setZ(sz);
+        Type t = tb.create();
+        mCube = Allocation.createTyped(mRS, t);
+
+        int dat[] = new int[sx * sy * sz];
+        for (int z = 0; z < sz; z++) {
+            for (int y = 0; y < sy; y++) {
+                for (int x = 0; x < sx; x++ ) {
+                    int v = 0xff000000;
+                    v |= (0xff * x / (sx - 1));
+                    v |= (0xff * y / (sy - 1)) << 8;
+                    v |= (0xff * z / (sz - 1)) << 16;
+                    dat[z*sy*sx + y*sx + x] = v;
+                }
+            }
+        }
+
+        mCube.copyFromUnchecked(dat);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_colorcube(mRS, res, R.raw.colorcube);
+        mIntrinsic = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+
+        initCube();
+        mScript.invoke_setCube(mCube);
+        mIntrinsic.setLUT(mCube);
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java b/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..3b0f86a
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Contrast.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Contrast.java
new file mode 100644
index 0000000..3ae5d2a
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Contrast.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+
+public class Contrast extends TestBase {
+    private ScriptC_contrast mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_contrast(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_setBright(50.f);
+        mScript.forEach_contrast(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..d4852f0
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,66 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_ip2_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_ip2_convolve3x3(mRS, res, R.raw.ip2_convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..d2da3c4
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,80 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Copy.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..ef71907
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Copy.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java b/java/tests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..96787d7
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Exposure.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Exposure.java
new file mode 100644
index 0000000..deb6b46
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Exposure.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+
+public class Exposure extends TestBase {
+    private ScriptC_exposure mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_exposure(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_setBright(50.f);
+        mScript.forEach_exposure(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
new file mode 100644
index 0000000..97beb88
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,135 @@
+/*
+ * 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 com.android.rs.image2;
+
+import android.support.v8.renderscript.*;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Fisheye extends TestBase {
+    private ScriptC_fisheye_full mScript_full = null;
+    private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+        else
+            mScript_full.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
+            mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
+                    R.raw.fisheye_relaxed);
+            mScript_relaxed.set_in_alloc(mInPixelsAllocation);
+            mScript_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        } else {
+            mScript_full = new ScriptC_fisheye_full(mRS, res,
+                    R.raw.fisheye_full);
+            mScript_full.set_in_alloc(mInPixelsAllocation);
+            mScript_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        }
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..dfd3c32
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java
@@ -0,0 +1,89 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(noiseW);
+        tb.setY(noiseH);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Greyscale.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..5b16e24
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.android.rs.image2;
+
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java b/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
new file mode 100644
index 0000000..a7ceebe
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
+
+    private Allocation mScratchPixelsAllocation1;
+    private ScriptGroup mGroup;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseNative;
+
+
+    public GroupTest(boolean useNative) {
+        mUseNative = useNative;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+        mConvolve.setCoefficients(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.setColorMatrix(m);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        Type connect = tb.create();
+
+        if (mUseNative) {
+            ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
+            mGroup = b.create();
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.setInput(mInPixelsAllocation);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
new file mode 100644
index 0000000..4b0e2dd
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -0,0 +1,470 @@
+/*
+ * 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 com.android.rs.image2;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.support.v8.renderscript.*;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class ImageProcessingActivity2 extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    public final String RESULT_FILE = "image_processing_result.csv";
+
+    RenderScript mRS;
+    Allocation mInPixelsAllocation;
+    Allocation mInPixelsAllocation2;
+    Allocation mOutPixelsAllocation;
+
+    /**
+     * Define enum type for test names
+     */
+    public enum TestName {
+        // totally there are 38 test cases
+        LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
+        LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
+        LEVELS_VEC3_FULL ("Levels Vec3 Full"),
+        LEVELS_VEC4_FULL ("Levels Vec4 Full"),
+        BLUR_RADIUS_25 ("Blur radius 25"),
+        INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
+        GREYSCALE ("Greyscale"),
+        GRAIN ("Grain"),
+        FISHEYE_FULL ("Fisheye Full"),
+        FISHEYE_RELAXED ("Fisheye Relaxed"),
+        FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
+        FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
+        VIGNETTE_FULL ("Vignette Full"),
+        VIGNETTE_RELAXED ("Vignette Relaxed"),
+        VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
+        VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
+        GROUP_TEST_EMULATED ("Group Test (emulated)"),
+        GROUP_TEST_NATIVE ("Group Test (native)"),
+        CONVOLVE_3X3 ("Convolve 3x3"),
+        INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
+        COLOR_MATRIX ("ColorMatrix"),
+        INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
+        INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
+        COPY ("Copy"),
+        CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
+        CONVOLVE_5X5 ("Convolve 5x5"),
+        INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
+        MANDELBROT ("Mandelbrot"),
+        INTRINSICS_BLEND ("Intrinsics Blend"),
+        INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar"),
+        VIBRANCE ("Vibrance"),
+        BW_FILTER ("BW Filter"),
+        SHADOWS ("Shadows"),
+        CONTRAST ("Contrast"),
+        EXPOSURE ("Exposure"),
+        WHITE_BALANCE ("White Balance"),
+        COLOR_CUBE ("Color Cube"),
+        COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)");
+
+
+        private final String name;
+
+        private TestName(String s) {
+            name = s;
+        }
+
+        // return quoted string as displayed test name
+        public String toString() {
+            return name;
+        }
+    }
+
+    Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
+    Bitmap mBitmapOut;
+
+    private Spinner mSpinner;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
+
+    private float mSaturation = 1.0f;
+
+    private TextView mBenchmarkResult;
+    private Spinner mTestSpinner;
+
+    private SurfaceView mSurfaceView;
+    private ImageView mDisplayView;
+
+    private boolean mDoingBenchmark;
+
+    private TestBase mTest;
+    private int mRunCount;
+
+    public void updateDisplay() {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+    }
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
+            }
+
+            mTest.runTest();
+            updateDisplay();
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(TestName testName) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
+        switch(testName) {
+        case LEVELS_VEC3_RELAXED:
+            mTest = new LevelsV4(false, false);
+            break;
+        case LEVELS_VEC4_RELAXED:
+            mTest = new LevelsV4(false, true);
+            break;
+        case LEVELS_VEC3_FULL:
+            mTest = new LevelsV4(true, false);
+            break;
+        case LEVELS_VEC4_FULL:
+            mTest = new LevelsV4(true, true);
+            break;
+        case BLUR_RADIUS_25:
+            mTest = new Blur25(false);
+            break;
+        case INTRINSIC_BLUE_RADIUS_25:
+            mTest = new Blur25(true);
+            break;
+        case GREYSCALE:
+            mTest = new Greyscale();
+            break;
+        case GRAIN:
+            mTest = new Grain();
+            break;
+        case FISHEYE_FULL:
+            mTest = new Fisheye(false, false);
+            break;
+        case FISHEYE_RELAXED:
+            mTest = new Fisheye(false, true);
+            break;
+        case FISHEYE_APPROXIMATE_FULL:
+            mTest = new Fisheye(true, false);
+            break;
+        case FISHEYE_APPROXIMATE_RELAXED:
+            mTest = new Fisheye(true, true);
+            break;
+        case VIGNETTE_FULL:
+            mTest = new Vignette(false, false);
+            break;
+        case VIGNETTE_RELAXED:
+            mTest = new Vignette(false, true);
+            break;
+        case VIGNETTE_APPROXIMATE_FULL:
+            mTest = new Vignette(true, false);
+            break;
+        case VIGNETTE_APPROXIMATE_RELAXED:
+            mTest = new Vignette(true, true);
+            break;
+        case GROUP_TEST_EMULATED:
+            mTest = new GroupTest(false);
+            break;
+        case GROUP_TEST_NATIVE:
+            mTest = new GroupTest(true);
+            break;
+        case CONVOLVE_3X3:
+            mTest = new Convolve3x3(false);
+            break;
+        case INTRINSICS_CONVOLVE_3X3:
+            mTest = new Convolve3x3(true);
+            break;
+        case COLOR_MATRIX:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case INTRINSICS_COLOR_MATRIX:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case INTRINSICS_COLOR_MATRIX_GREY:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case COPY:
+            mTest = new Copy();
+            break;
+        case CROSS_PROCESS_USING_LUT:
+            mTest = new CrossProcess();
+            break;
+        case CONVOLVE_5X5:
+            mTest = new Convolve5x5(false);
+            break;
+        case INTRINSICS_CONVOLVE_5X5:
+            mTest = new Convolve5x5(true);
+            break;
+        case MANDELBROT:
+            mTest = new Mandelbrot();
+            break;
+        case INTRINSICS_BLEND:
+            mTest = new Blend();
+            break;
+        case INTRINSICS_BLUR_25G:
+            mTest = new Blur25G();
+            break;
+        case VIBRANCE:
+            mTest = new Vibrance();
+            break;
+        case BW_FILTER:
+            mTest = new BWFilter();
+            break;
+        case SHADOWS:
+            mTest = new Shadows();
+            break;
+        case CONTRAST:
+            mTest = new Contrast();
+            break;
+        case EXPOSURE:
+            mTest = new Exposure();
+            break;
+        case WHITE_BALANCE:
+            mTest = new WhiteBalance();
+            break;
+        case COLOR_CUBE:
+            mTest = new ColorCube(false);
+            break;
+        case COLOR_CUBE_3D_INTRINSIC:
+            mTest = new ColorCube(true);
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
+        setupBars();
+
+        mTest.runTest();
+        updateDisplay();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
+            this, R.layout.spinner_layout, TestName.values()));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(TestName.values()[pos]);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
+                                         mBitmapIn.getConfig());
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
+
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
+
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
+
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+
+        mRS = RenderScript.create(this);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
+
+
+        setupTests();
+        changeTest(TestName.LEVELS_VEC3_RELAXED);
+    }
+
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        return BitmapFactory.decodeResource(getResources(), resource, options);
+    }
+
+    // button hook
+    public void benchmark(View v) {
+        float t = getBenchmark();
+        //long javaTime = javaFilter();
+        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
+        mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        //resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (TestName tn: TestName.values()) {
+                changeTest(tn);
+                float t = getBenchmark();
+                String s = new String("" + tn.toString() + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(TestName.LEVELS_VEC3_RELAXED);
+    }
+
+    // For benchmark test
+    public float getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
+        t = java.lang.System.currentTimeMillis();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
+        t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
+
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
+        return ft;
+    }
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java b/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..fbe3727
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,161 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..1780587
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Shadows.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Shadows.java
new file mode 100644
index 0000000..353c56d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Shadows.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.android.rs.image2;
+
+
+public class Shadows extends TestBase {
+    private ScriptC_shadows mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_shadows(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_prepareShadows(50.f);
+        mScript.forEach_shadowsKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..eeabc73
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.android.rs.image2;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.support.v8.renderscript.*;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+import android.widget.Spinner;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
+    protected Allocation mOutPixelsAllocation;
+
+    protected ImageProcessingActivity2 act;
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2, Bitmap outb) {
+        act = ipact;
+        mRS = ipact.mRS;
+
+        mInPixelsAllocation = ipact.mInPixelsAllocation;
+        mInPixelsAllocation2 = ipact.mInPixelsAllocation2;
+        mOutPixelsAllocation = ipact.mOutPixelsAllocation;
+
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void destroy() {
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Vibrance.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Vibrance.java
new file mode 100644
index 0000000..37c0aa7
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Vibrance.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.android.rs.image2;
+
+public class Vibrance extends TestBase {
+    private ScriptC_vibrance mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_vibrance(mRS);
+    }
+
+    public void runTest() {
+        mScript.set_vibrance(50.f);
+        mScript.invoke_prepareVibrance();
+        mScript.forEach_vibranceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java
new file mode 100644
index 0000000..9f6d34d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,150 @@
+/*
+ * 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 com.android.rs.image2;
+
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Vignette extends TestBase {
+    private ScriptC_vignette_full mScript_full = null;
+    private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+    private float shade = 0.5f;
+    private float slope = 20.0f;
+
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shade");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Slope");
+        b.setMax(100);
+        b.setProgress(20);
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        shade = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        slope = (float)progress;
+        do_init();
+    }
+    public void onBar4Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar5Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+        else
+            mScript_full.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
+            mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
+                    R.raw.vignette_relaxed);
+        else
+            mScript_full = new ScriptC_vignette_full(mRS, res,
+                    R.raw.vignette_full);
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java b/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
new file mode 100644
index 0000000..658e3b1
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+
+public class WhiteBalance extends TestBase {
+    private ScriptC_wbalance mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_wbalance(mRS);
+    }
+
+    public void runTest() {
+        mScript.set_histogramSource(mInPixelsAllocation);
+        mScript.set_histogramWidth(mInPixelsAllocation.getType().getX());
+        mScript.set_histogramHeight(mInPixelsAllocation.getType().getY());
+        mScript.invoke_prepareWhiteBalance();
+        mScript.forEach_whiteBalanceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..9ec1246
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -0,0 +1,23 @@
+// 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.
+
+#include "ip.rsh"
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
new file mode 100644
index 0000000..e706d44
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static float sr = 0.f;
+static float sg = 0.f;
+static float sb = 0.f;
+
+void prepareBwFilter(uint32_t rw, uint32_t gw, uint32_t bw) {
+
+    sr = rw;
+    sg = gw;
+    sb = bw;
+
+    float imageMin = min(sg,sb);
+    imageMin = fmin(sr,imageMin);
+    float imageMax = max(sg,sb);
+    imageMax = fmax(sr,imageMax);
+    float avg = (imageMin + imageMax)/2;
+    sb /= avg;
+    sg /= avg;
+    sr /= avg;
+
+}
+
+void bwFilterKernel(const uchar4 *in, uchar4 *out) {
+    float r = in->r * sr;
+    float g = in->g * sg;
+    float b = in->b * sb;
+    float localMin, localMax, avg;
+    localMin = fmin(g,b);
+    localMin = fmin(r,localMin);
+    localMax = fmax(g,b);
+    localMax = fmax(r,localMax);
+    avg = (localMin+localMax) * 0.5f;
+    out->r = out->g = out->b = rsClamp(avg, 0, 255);
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
new file mode 100644
index 0000000..4f1e73e
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+
+static rs_allocation gCube;
+static int4 gDims;
+static int4 gCoordMul;
+
+
+void setCube(rs_allocation c) {
+    gCube = c;
+    gDims.x = rsAllocationGetDimX(gCube);
+    gDims.y = rsAllocationGetDimY(gCube);
+    gDims.z = rsAllocationGetDimZ(gCube);
+    gDims.w = 0;
+
+    float4 m = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
+    gCoordMul = convert_int4(m * (float4)0x10000);
+
+    rsDebug("dims", gDims);
+    rsDebug("gCoordMul", gCoordMul);
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    //rsDebug("root", in);
+
+    int4 baseCoord = convert_int4(*in) * gCoordMul;
+    int4 coord1 = baseCoord >> (int4)16;
+    int4 coord2 = min(coord1 + 1, gDims - 1);
+
+    int4 weight2 = baseCoord & 0xffff;
+    int4 weight1 = (int4)0x10000 - weight2;
+
+    uint4 v000 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord1.z));
+    uint4 v100 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord1.z));
+    uint4 v010 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord1.z));
+    uint4 v110 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord1.z));
+    uint4 v001 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord2.z));
+    uint4 v101 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord2.z));
+    uint4 v011 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord2.z));
+    uint4 v111 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord2.z));
+
+    uint4 yz00 = ((v000 * weight1.x) + (v100 * weight2.x)) >> (int4)8;
+    uint4 yz10 = ((v010 * weight1.x) + (v110 * weight2.x)) >> (int4)8;
+    uint4 yz01 = ((v001 * weight1.x) + (v101 * weight2.x)) >> (int4)8;
+    uint4 yz11 = ((v011 * weight1.x) + (v111 * weight2.x)) >> (int4)8;
+
+    uint4 z0 = ((yz00 * weight1.y) + (yz10 * weight2.y)) >> (int4)16;
+    uint4 z1 = ((yz01 * weight1.y) + (yz11 * weight2.y)) >> (int4)16;
+
+    uint4 v = ((z0 * weight1.z) + (z1 * weight2.z)) >> (int4)16;
+    uint4 v2 = (v + 0x7f) >> (int4)8;
+
+    *out = convert_uchar4(v2);
+    out->a = 0xff;
+
+    #if 0
+    if (in->r != out->r) {
+        rsDebug("dr", in->r - out->r);
+        //rsDebug("in", convert_int4(*in));
+        //rsDebug("coord1", coord1);
+        //rsDebug("coord2", coord2);
+        //rsDebug("weight1", weight1);
+        //rsDebug("weight2", weight2);
+        //rsDebug("yz00", yz00);
+        //rsDebug("z0", z0);
+        //rsDebug("v", v);
+        //rsDebug("v2", v2);
+        //rsDebug("out", convert_int4(*out));
+    }
+    #endif
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
new file mode 100644
index 0000000..86fb248
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static rs_matrix4x4 Mat;
+
+void init() {
+    rsMatrixLoadIdentity(&Mat);
+}
+
+void setMatrix(rs_matrix4x4 m) {
+    Mat = m;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    float4 f = convert_float4(in);
+    f = rsMatrixMultiply(&Mat, f);
+    f = clamp(f, 0.f, 255.f);
+    return convert_uchar4(f);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs
new file mode 100644
index 0000000..d3743d3
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static float brightM = 0.f;
+static float brightC = 0.f;
+
+void setBright(float v) {
+    brightM = pow(2.f, v / 100.f);
+    brightC = 127.f - brightM * 127.f;
+}
+
+void contrast(const uchar4 *in, uchar4 *out)
+{
+#if 0
+    out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
+    out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
+    out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
+#else
+    float3 v = convert_float3(in->rgb) * brightM + brightC;
+    out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+#endif
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
new file mode 100644
index 0000000..922a593
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    return convert_uchar4(p0);
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs
new file mode 100644
index 0000000..6595874
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    return v_in;
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs
new file mode 100644
index 0000000..0f05cb9
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static float bright = 0.f;
+
+void setBright(float v) {
+    bright = 255.f / (255.f - v);
+}
+
+void exposure(const uchar4 *in, uchar4 *out)
+{
+    out->r = rsClamp((int)(bright * in->r), 0, 255);
+    out->g = rsClamp((int)(bright * in->g), 0, 255);
+    out->b = rsClamp((int)(bright * in->b), 0, 255);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..2eacb7d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..fcf0a3d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..ed69ff4
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye_approx.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
new file mode 100644
index 0000000..ed69ff4
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye_approx.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
new file mode 100644
index 0000000..f986b5d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
new file mode 100644
index 0000000..f986b5d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/grain.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/grain.fs
new file mode 100644
index 0000000..2e62cd7
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/grain.fs
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+uchar __attribute__((kernel)) genRand() {
+    return (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWMask;
+int32_t gHMask;
+
+rs_allocation gBlendSource;
+uchar __attribute__((kernel)) blend9(uint32_t x, uint32_t y) {
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
+
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = min(p20 >> 10, (uint)255);
+    return (uchar)p20;
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(in);
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    return p;
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
new file mode 100644
index 0000000..4e13072
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    float4 f4 = rsUnpackColor8888(v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    return rsPackColorTo8888(mono);
+}
+
+uchar __attribute__((kernel)) toU8(uchar4 v_in) {
+    float4 f4 = convert_float4(v_in);
+    return (uchar)dot(f4.rgb, gMonoMult);
+}
+
+uchar4 __attribute__((kernel)) toU8_4(uchar v_in) {
+    return (uchar4)v_in;
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ip.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/ip.rsh
new file mode 100644
index 0000000..34e213c
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ip.rsh
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
new file mode 100644
index 0000000..177e86e
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
+    p00 *= gCoeffs[0];
+    p01 *= gCoeffs[1];
+    p02 *= gCoeffs[2];
+    p10 *= gCoeffs[3];
+    p11 *= gCoeffs[4];
+    p12 *= gCoeffs[5];
+    p20 *= gCoeffs[6];
+    p21 *= gCoeffs[7];
+    p22 *= gCoeffs[8];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = clamp(p20, 0.f, 255.f);
+    return convert_uchar4(p20);
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..e289906
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    uchar4 out;
+    float3 pixel = convert_float4(in).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out.xyz = convert_uchar3(pixel);
+    out.w = 0xff;
+    return out;
+}
+
+uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(in);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    return convert_uchar4(pixel);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/levels_full.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
new file mode 100644
index 0000000..28596ba
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "levels.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
new file mode 100644
index 0000000..28596ba
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "levels.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..de0bd00
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,55 @@
+// 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.
+
+#include "ip.rsh"
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    return (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.f;
+    if (iter <= (gMaxIteration / 3))
+      return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                      (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                      (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs
new file mode 100644
index 0000000..f6c149d
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static double shadowFilterMap[] = {
+    -0.00591,  0.0001,
+     1.16488,  0.01668,
+    -0.18027, -0.06791,
+    -0.12625,  0.09001,
+     0.15065, -0.03897
+};
+
+static double poly[] = {
+    0., 0.,
+    0., 0.,
+    0.
+};
+
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static double fastevalPoly(double *poly,int n, double x){
+
+    double f =x;
+    double sum = poly[0]+poly[1]*f;
+    int i;
+    for (i = 2; i < n; i++) {
+        f*=x;
+        sum += poly[i]*f;
+    }
+    return sum;
+}
+
+static ushort3 rgb2hsv( uchar4 rgb)
+{
+    int iMin,iMax,chroma;
+
+    int ri = rgb.r;
+    int gi = rgb.g;
+    int bi = rgb.b;
+    short rv,rs,rh;
+
+    if (ri > gi) {
+        iMax = max (ri, bi);
+        iMin = min (gi, bi);
+    } else {
+        iMax = max (gi, bi);
+        iMin = min (ri, bi);
+    }
+
+    chroma = iMax - iMin;
+    // set value
+    rv = (short)( iMax << ABITS);
+
+    // set saturation
+    if (rv == 0)
+        rs = 0;
+    else
+        rs = (short)((k1*chroma)/iMax);
+
+    // set hue
+    if (rs == 0)
+        rh = 0;
+    else {
+        if ( ri == iMax ) {
+            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
+            if (rh >= k2) rh -= k2;
+        } else if (gi  == iMax)
+            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
+        else // (bi == iMax )
+                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
+    }
+
+    ushort3 out;
+    out.x = rv;
+    out.y = rs;
+    out.z = rh;
+    return out;
+}
+
+static uchar4 hsv2rgb(ushort3 hsv)
+{
+    int ABITS = 4;
+    int HSCALE = 256;
+    int m;
+    int H,X,ih,is,iv;
+    int k1=255<<ABITS;
+    int k2=HSCALE<<ABITS;
+    int k3=1<<(ABITS-1);
+    int rr=0;
+    int rg=0;
+    int rb=0;
+    short cv = hsv.x;
+    short cs = hsv.y;
+    short ch = hsv.z;
+
+    // set chroma and min component value m
+    //chroma = ( cv * cs )/k1;
+    //m = cv - chroma;
+    m = ((int)cv*(k1 - (int)cs ))/k1;
+
+    // chroma  == 0 <-> cs == 0 --> m=cv
+    if (cs == 0) {
+        rb = ( rg = ( rr =( cv >> ABITS) ));
+    } else {
+        ih=(int)ch;
+        is=(int)cs;
+        iv=(int)cv;
+
+        H = (6*ih)/k2;
+        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
+
+        // removing additional bits --> unit8
+        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
+        m=m >> ABITS;
+
+        // ( chroma + m ) --> cv ;
+        cv=(short) (cv >> ABITS);
+        switch (H) {
+        case 0:
+            rr = cv;
+            rg = X;
+            rb = m;
+            break;
+        case 1:
+            rr = X;
+            rg = cv;
+            rb = m;
+            break;
+        case 2:
+            rr = m;
+            rg = cv;
+            rb = X;
+            break;
+        case 3:
+            rr = m;
+            rg = X;
+            rb = cv;
+            break;
+        case 4:
+            rr = X;
+            rg = m;
+            rb = cv;
+            break;
+        case 5:
+            rr = cv;
+            rg = m ;
+            rb = X;
+            break;
+        }
+    }
+
+    uchar4 rgb;
+
+    rgb.r =  rr;
+    rgb.g =  rg;
+    rgb.b =  rb;
+
+    return rgb;
+}
+
+void prepareShadows(float scale) {
+    double s = (scale>=0)?scale:scale/5;
+    for (int i = 0; i < 5; i++) {
+        poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
+    }
+}
+
+void shadowsKernel(const uchar4 *in, uchar4 *out) {
+    ushort3 hsv = rgb2hsv(*in);
+    double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
+    if (v>4080) v = 4080;
+    hsv.x = (unsigned short) ((v>0)?v:0);
+    *out = hsv2rgb(hsv);
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.fs
new file mode 100644
index 0000000..0b2c2e8
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.fs
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+
+int height;
+int width;
+static int radius;
+
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+void setRadius(int rad) {
+    radius = rad;
+    // Compute gaussian weights for the blur
+    // e is the euler's number
+    float e = 2.718281828459045f;
+    float pi = 3.1415926535897932f;
+    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+    // x is of the form [-radius .. 0 .. radius]
+    // and sigma varies with radius.
+    // Based on some experimental radius values and sigma's
+    // we approximately fit sigma = f(radius) as
+    // sigma = radius * 0.4  + 0.6
+    // The larger the radius gets, the more our gaussian blur
+    // will resemble a box blur since with large sigma
+    // the gaussian curve begins to lose its shape
+    float sigma = 0.4f * (float)radius + 0.6f;
+
+    // Now compute the coefficints
+    // We will store some redundant values to save some math during
+    // the blur calculations
+    // precompute some values
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    //Now we need to normalize the weights because all our coefficients need to add up to one
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+float4 __attribute__((kernel)) copyIn(uchar4 in) {
+    return convert_float4(in);
+}
+
+uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    int gi = 0;
+    uchar4 out;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    }
+
+    out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out.w = 0xff;
+    return out;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    }
+
+    return blurredPixel;
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
new file mode 100644
index 0000000..ad4de58
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+float vibrance = 0.f;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+static float S  = 0.f;
+static float MS = 0.f;
+static float Rt = 0.f;
+static float Gt = 0.f;
+static float Bt = 0.f;
+static float Vib = 0.f;
+
+void vibranceKernel(const uchar4 *in, uchar4 *out) {
+
+    float R, G, B;
+
+    int r = in->r;
+    int g = in->g;
+    int b = in->b;
+    float red = (r-max(g, b))/256.f;
+    float sx = (float)(Vib/(1+native_exp(-red*3)));
+    S = sx+1;
+    MS = 1.0f - S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+    int t = (r + g) / 2;
+    R = r;
+    G = g;
+    B = b;
+
+    float Rc = R * (Rt + S) + G * Gt + B * Bt;
+    float Gc = R * Rt + G * (Gt + S) + B * Bt;
+    float Bc = R * Rt + G * Gt + B * (Bt + S);
+
+    out->r = rsClamp(Rc, 0, 255);
+    out->g = rsClamp(Gc, 0, 255);
+    out->b = rsClamp(Bc, 0, 255);
+
+}
+
+void prepareVibrance() {
+
+    Vib = vibrance/100.f;
+    S  = Vib + 1;
+    MS = 1.0f - S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
new file mode 100644
index 0000000..04ca1f1
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade / ( 1.0f + sloped_neg_range * exp(sloped_dist_ratio) );
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..5668621
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * native_exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..00cbbc4
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette_approx.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
new file mode 100644
index 0000000..00cbbc4
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette_approx.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
new file mode 100644
index 0000000..8202c5c
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
new file mode 100644
index 0000000..8202c5c
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette.rsh"
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
new file mode 100644
index 0000000..6650671
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
+
+rs_allocation histogramSource;
+uint32_t histogramHeight;
+uint32_t histogramWidth;
+
+static float scaleR;
+static float scaleG;
+static float scaleB;
+
+static uchar4 estimateWhite() {
+
+    for (int i = 0; i < 256; i++) {
+        histR[i] = 0; histG[i] = 0; histB[i] = 0;
+    }
+
+    for (uint32_t i = 0; i < histogramHeight; i++) {
+        for (uint32_t j = 0; j < histogramWidth; j++) {
+            uchar4 in = rsGetElementAt_uchar4(histogramSource, j, i);
+            histR[in.r]++;
+            histG[in.g]++;
+            histB[in.b]++;
+        }
+    }
+
+    int min_r = -1, min_g = -1, min_b = -1;
+    int max_r =  0, max_g =  0, max_b =  0;
+    int sum_r =  0, sum_g =  0, sum_b =  0;
+
+    for (int i = 1; i < 255; i++) {
+        int r = histR[i];
+        int g = histG[i];
+        int b = histB[i];
+        sum_r += r;
+        sum_g += g;
+        sum_b += b;
+
+        if (r>0){
+            if (min_r < 0) min_r = i;
+            max_r = i;
+        }
+        if (g>0){
+            if (min_g < 0) min_g = i;
+            max_g = i;
+        }
+        if (b>0){
+            if (min_b < 0) min_b = i;
+            max_b = i;
+        }
+    }
+
+    int sum15r = 0, sum15g = 0, sum15b = 0;
+    int count15r = 0, count15g = 0, count15b = 0;
+    int tmp_r = 0, tmp_g = 0, tmp_b = 0;
+
+    for (int i = 254; i >0; i--) {
+        int r = histR[i];
+        int g = histG[i];
+        int b = histB[i];
+        tmp_r += r;
+        tmp_g += g;
+        tmp_b += b;
+
+        if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
+            sum15r += r*i;
+            count15r += r;
+        }
+        if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
+            sum15g += g*i;
+            count15g += g;
+        }
+        if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
+            sum15b += b*i;
+            count15b += b;
+        }
+
+    }
+
+    uchar4 out;
+
+    if ((count15r>0) && (count15g>0) && (count15b>0) ){
+        out.r = sum15r/count15r;
+        out.g = sum15g/count15g;
+        out.b = sum15b/count15b;
+    }else {
+        out.r = out.g = out.b = 255;
+    }
+
+    return out;
+
+}
+
+void prepareWhiteBalance() {
+    uchar4 estimation = estimateWhite();
+    int minimum = min(estimation.r, min(estimation.g, estimation.b));
+    int maximum = max(estimation.r, max(estimation.g, estimation.b));
+    float avg = (minimum + maximum) / 2.f;
+
+    scaleR =  avg/estimation.r;
+    scaleG =  avg/estimation.g;
+    scaleB =  avg/estimation.b;
+
+}
+
+static unsigned char contrastClamp(int c)
+{
+    int N = 255;
+    c &= ~(c >> 31);
+    c -= N;
+    c &= (c >> 31);
+    c += N;
+    return  (unsigned char) c;
+}
+
+void whiteBalanceKernel(const uchar4 *in, uchar4 *out) {
+    float Rc =  in->r*scaleR;
+    float Gc =  in->g*scaleG;
+    float Bc =  in->b*scaleB;
+
+    out->r = contrastClamp(Rc);
+    out->g = contrastClamp(Gc);
+    out->b = contrastClamp(Bc);
+}
diff --git a/java/tests/ImageProcessing_jb/Android.mk b/java/tests/ImageProcessing_jb/Android.mk
new file mode 100644
index 0000000..20d6be7
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/Android.mk
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := ImageProcessingJB
+LOCAL_SDK_VERSION := 17
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/ImageProcessing_jb/AndroidManifest.xml b/java/tests/ImageProcessing_jb/AndroidManifest.xml
new file mode 100644
index 0000000..b3fcfc4
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.imagejb">
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="11" />
+    <application android:label="Image Processing JB"
+                 android:hardwareAccelerated="true">
+        <activity android:name="ImageProcessingActivityJB">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067.jpg b/java/tests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067b.jpg b/java/tests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing_jb/res/layout/main.xml b/java/tests/ImageProcessing_jb/res/layout/main.xml
new file mode 100644
index 0000000..f0a2b92
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/res/layout/main.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider1Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/slider1"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider2Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/slider2"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider3Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/slider3"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider4Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider4"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider5Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider5"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/java/tests/ImageProcessing_jb/res/layout/spinner_layout.xml b/java/tests/ImageProcessing_jb/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/java/tests/ImageProcessing_jb/res/values/strings.xml b/java/tests/ImageProcessing_jb/res/values/strings.xml
new file mode 100644
index 0000000..a7dd165
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <!--slider label -->
+    <string name="blur_description">Blur Radius</string>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
+
+</resources>
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/BWFilter.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/BWFilter.java
new file mode 100644
index 0000000..4870ac4
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/BWFilter.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+
+public class BWFilter extends TestBase {
+    private ScriptC_bwfilter mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_bwfilter(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_prepareBwFilter(50, 50, 50);
+        mScript.forEach_bwFilterKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Blend.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..302dc31
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Blend.java
@@ -0,0 +1,178 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicBlend;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    if (mRS != null) {
+                        runTest();
+                        act.updateDisplay();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..90acd00
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
+
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
+    }
+
+    public void setupBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
+    }
+
+    public void exitBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
+    }
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..5053d4d
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Contrast.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Contrast.java
new file mode 100644
index 0000000..20b28ff
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Contrast.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Contrast extends TestBase {
+    private ScriptC_contrast mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_contrast(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_setBright(50.f);
+        mScript.forEach_contrast(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..d7acf4a
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..d1dbb1f
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,88 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve5x5;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Copy.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..1bdee4b
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Copy.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/CrossProcess.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..75ee39b
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicLUT;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Exposure.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Exposure.java
new file mode 100644
index 0000000..ddde96f
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Exposure.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Exposure extends TestBase {
+    private ScriptC_exposure mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_exposure(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_setBright(50.f);
+        mScript.forEach_exposure(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Fisheye.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Fisheye.java
new file mode 100644
index 0000000..114839c
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,138 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Fisheye extends TestBase {
+    private ScriptC_fisheye_full mScript_full = null;
+    private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+        else
+            mScript_full.invoke_init_filter(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
+            mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
+                    R.raw.fisheye_relaxed);
+            mScript_relaxed.set_in_alloc(mInPixelsAllocation);
+            mScript_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        } else {
+            mScript_full = new ScriptC_fisheye_full(mRS, res,
+                    R.raw.fisheye_full);
+            mScript_full.set_in_alloc(mInPixelsAllocation);
+            mScript_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+        }
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Grain.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..5cd19a2
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Grain.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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(noiseW);
+        tb.setY(noiseH);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Greyscale.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..f1952e7
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/GroupTest.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/GroupTest.java
new file mode 100644
index 0000000..3e5175a
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/GroupTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.renderscript.Matrix4f;
+import android.renderscript.ScriptGroup;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
+
+    private Allocation mScratchPixelsAllocation1;
+    private ScriptGroup mGroup;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseNative;
+
+
+    public GroupTest(boolean useNative) {
+        mUseNative = useNative;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+        mConvolve.setCoefficients(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.setColorMatrix(m);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        Type connect = tb.create();
+
+        if (mUseNative) {
+            ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
+            mGroup = b.create();
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.setInput(mInPixelsAllocation);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
new file mode 100644
index 0000000..93937ef
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
@@ -0,0 +1,494 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.view.SurfaceView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+
+import android.os.Environment;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class ImageProcessingActivityJB extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    public final String RESULT_FILE = "image_processing_result.csv";
+
+    RenderScript mRS;
+    Allocation mInPixelsAllocation;
+    Allocation mInPixelsAllocation2;
+    Allocation mOutPixelsAllocation;
+
+    /**
+     * Define enum type for test names
+     */
+    public enum TestName {
+        // totally there are 38 test cases
+        LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
+        LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
+        LEVELS_VEC3_FULL ("Levels Vec3 Full"),
+        LEVELS_VEC4_FULL ("Levels Vec4 Full"),
+        BLUR_RADIUS_25 ("Blur radius 25"),
+        INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
+        GREYSCALE ("Greyscale"),
+        GRAIN ("Grain"),
+        FISHEYE_FULL ("Fisheye Full"),
+        FISHEYE_RELAXED ("Fisheye Relaxed"),
+        FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
+        FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
+        VIGNETTE_FULL ("Vignette Full"),
+        VIGNETTE_RELAXED ("Vignette Relaxed"),
+        VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
+        VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
+        GROUP_TEST_EMULATED ("Group Test (emulated)"),
+        GROUP_TEST_NATIVE ("Group Test (native)"),
+        CONVOLVE_3X3 ("Convolve 3x3"),
+        INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
+        COLOR_MATRIX ("ColorMatrix"),
+        INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
+        INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
+        COPY ("Copy"),
+        CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
+        CONVOLVE_5X5 ("Convolve 5x5"),
+        INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
+        MANDELBROT ("Mandelbrot"),
+        INTRINSICS_BLEND ("Intrinsics Blend"),
+        VIBRANCE ("Vibrance"),
+        BW_FILTER ("BW Filter"),
+        SHADOWS ("Shadows"),
+        CONTRAST ("Contrast"),
+        EXPOSURE ("Exposure"),
+        WHITE_BALANCE ("White Balance");
+
+
+        private final String name;
+
+        private TestName(String s) {
+            name = s;
+        }
+
+        // return quoted string as displayed test name
+        public String toString() {
+            return name;
+        }
+    }
+
+    Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
+    Bitmap mBitmapOut;
+
+    private Spinner mSpinner;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
+
+    private float mSaturation = 1.0f;
+
+    private TextView mBenchmarkResult;
+    private Spinner mTestSpinner;
+
+    private SurfaceView mSurfaceView;
+    private ImageView mDisplayView;
+
+    private boolean mDoingBenchmark;
+
+    private TestBase mTest;
+    private int mRunCount;
+
+    public void updateDisplay() {
+        mHandler.sendMessage(Message.obtain());
+    }
+
+    private Handler mHandler = new Handler() {
+        // Allow the filter to complete without blocking the UI
+        // thread.  When the message arrives that the op is complete
+        // we will either mark completion or start a new filter if
+        // more work is ready.  Either way, display the result.
+        @Override
+        public void handleMessage(Message msg) {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount > 0) {
+                    mRunCount--;
+                    if (mRunCount > 0) {
+                        doTest = true;
+                    }
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
+        }
+
+    };
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
+            }
+
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount == 0) {
+                    doTest = true;
+                    mRunCount = 1;
+                } else {
+                    mRunCount = 2;
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(TestName testName) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
+        switch(testName) {
+        case LEVELS_VEC3_RELAXED:
+            mTest = new LevelsV4(false, false);
+            break;
+        case LEVELS_VEC4_RELAXED:
+            mTest = new LevelsV4(false, true);
+            break;
+        case LEVELS_VEC3_FULL:
+            mTest = new LevelsV4(true, false);
+            break;
+        case LEVELS_VEC4_FULL:
+            mTest = new LevelsV4(true, true);
+            break;
+        case BLUR_RADIUS_25:
+            mTest = new Blur25(false);
+            break;
+        case INTRINSIC_BLUE_RADIUS_25:
+            mTest = new Blur25(true);
+            break;
+        case GREYSCALE:
+            mTest = new Greyscale();
+            break;
+        case GRAIN:
+            mTest = new Grain();
+            break;
+        case FISHEYE_FULL:
+            mTest = new Fisheye(false, false);
+            break;
+        case FISHEYE_RELAXED:
+            mTest = new Fisheye(false, true);
+            break;
+        case FISHEYE_APPROXIMATE_FULL:
+            mTest = new Fisheye(true, false);
+            break;
+        case FISHEYE_APPROXIMATE_RELAXED:
+            mTest = new Fisheye(true, true);
+            break;
+        case VIGNETTE_FULL:
+            mTest = new Vignette(false, false);
+            break;
+        case VIGNETTE_RELAXED:
+            mTest = new Vignette(false, true);
+            break;
+        case VIGNETTE_APPROXIMATE_FULL:
+            mTest = new Vignette(true, false);
+            break;
+        case VIGNETTE_APPROXIMATE_RELAXED:
+            mTest = new Vignette(true, true);
+            break;
+        case GROUP_TEST_EMULATED:
+            mTest = new GroupTest(false);
+            break;
+        case GROUP_TEST_NATIVE:
+            mTest = new GroupTest(true);
+            break;
+        case CONVOLVE_3X3:
+            mTest = new Convolve3x3(false);
+            break;
+        case INTRINSICS_CONVOLVE_3X3:
+            mTest = new Convolve3x3(true);
+            break;
+        case COLOR_MATRIX:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case INTRINSICS_COLOR_MATRIX:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case INTRINSICS_COLOR_MATRIX_GREY:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case COPY:
+            mTest = new Copy();
+            break;
+        case CROSS_PROCESS_USING_LUT:
+            mTest = new CrossProcess();
+            break;
+        case CONVOLVE_5X5:
+            mTest = new Convolve5x5(false);
+            break;
+        case INTRINSICS_CONVOLVE_5X5:
+            mTest = new Convolve5x5(true);
+            break;
+        case MANDELBROT:
+            mTest = new Mandelbrot();
+            break;
+        case INTRINSICS_BLEND:
+            mTest = new Blend();
+            break;
+        case VIBRANCE:
+            mTest = new Vibrance();
+            break;
+        case BW_FILTER:
+            mTest = new BWFilter();
+            break;
+        case SHADOWS:
+            mTest = new Shadows();
+            break;
+        case CONTRAST:
+            mTest = new Contrast();
+            break;
+        case EXPOSURE:
+            mTest = new Exposure();
+            break;
+        case WHITE_BALANCE:
+            mTest = new WhiteBalance();
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
+        setupBars();
+
+        mTest.runTest();
+        updateDisplay();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
+            this, R.layout.spinner_layout, TestName.values()));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(TestName.values()[pos]);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
+                                         mBitmapIn.getConfig());
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
+
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
+
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
+
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+
+        mRS = RenderScript.create(this);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
+
+
+        setupTests();
+        changeTest(TestName.LEVELS_VEC3_RELAXED);
+    }
+
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        return BitmapFactory.decodeResource(getResources(), resource, options);
+    }
+
+    // button hook
+    public void benchmark(View v) {
+        float t = getBenchmark();
+        //long javaTime = javaFilter();
+        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
+        mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (TestName tn: TestName.values()) {
+                changeTest(tn);
+                float t = getBenchmark();
+                String s = new String("" + tn.toString() + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(TestName.LEVELS_VEC3_RELAXED);
+    }
+
+    // For benchmark test
+    public float getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
+        t = java.lang.System.currentTimeMillis();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
+        t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
+
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
+        return ft;
+    }
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/LevelsV4.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..741e480
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,167 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Matrix3f;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Mandelbrot.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..ca34848
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,98 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Shadows.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Shadows.java
new file mode 100644
index 0000000..d246d59
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Shadows.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Shadows extends TestBase {
+    private ScriptC_shadows mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_shadows(mRS);
+    }
+
+    public void runTest() {
+        mScript.invoke_prepareShadows(50.f);
+        mScript.forEach_shadowsKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..9ae366a
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,153 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+import android.widget.Spinner;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
+    protected Allocation mOutPixelsAllocation;
+    protected ScriptC_msg mMessageScript;
+
+    protected ImageProcessingActivityJB act;
+
+    private class MessageProcessor extends RenderScript.RSMessageHandler {
+        ImageProcessingActivityJB mAct;
+
+        MessageProcessor(ImageProcessingActivityJB act) {
+            mAct = act;
+        }
+
+        public void run() {
+            mAct.updateDisplay();
+        }
+    }
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivityJB ipact, Bitmap b, Bitmap b2, Bitmap outb) {
+        act = ipact;
+        mRS = ipact.mRS;
+        mRS.setMessageHandler(new MessageProcessor(act));
+
+        mInPixelsAllocation = ipact.mInPixelsAllocation;
+        mInPixelsAllocation2 = ipact.mInPixelsAllocation2;
+        mOutPixelsAllocation = ipact.mOutPixelsAllocation;
+
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    final public void runTestSendMessage() {
+        runTest();
+        mMessageScript.invoke_sendMsg();
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void destroy() {
+        mRS.setMessageHandler(null);
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Vibrance.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Vibrance.java
new file mode 100644
index 0000000..09822a9
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Vibrance.java
@@ -0,0 +1,36 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Vibrance extends TestBase {
+    private ScriptC_vibrance mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_vibrance(mRS);
+    }
+
+    public void runTest() {
+        mScript.set_vibrance(50.f);
+        mScript.invoke_prepareVibrance();
+        mScript.forEach_vibranceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
new file mode 100644
index 0000000..9451757
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,154 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Vignette extends TestBase {
+    private ScriptC_vignette_full mScript_full = null;
+    private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+    private float shade = 0.5f;
+    private float slope = 20.0f;
+
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shade");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Slope");
+        b.setMax(100);
+        b.setProgress(20);
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        shade = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        slope = (float)progress;
+        do_init();
+    }
+    public void onBar4Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar5Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
+            mScript_relaxed.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+        else
+            mScript_full.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
+            mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
+                    R.raw.vignette_relaxed);
+        else
+            mScript_full = new ScriptC_vignette_full(mRS, res,
+                    R.raw.vignette_full);
+        do_init();
+    }
+
+    public void runTest() {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/WhiteBalance.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/WhiteBalance.java
new file mode 100644
index 0000000..f15aaf5
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/WhiteBalance.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class WhiteBalance extends TestBase {
+    private ScriptC_wbalance mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_wbalance(mRS);
+    }
+
+    public void runTest() {
+        mScript.set_histogramSource(mInPixelsAllocation);
+        mScript.set_histogramWidth(mInPixelsAllocation.getType().getX());
+        mScript.set_histogramHeight(mInPixelsAllocation.getType().getY());
+        mScript.invoke_prepareWhiteBalance();
+        mScript.forEach_whiteBalanceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/blend.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..9ec1246
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/blend.rs
@@ -0,0 +1,23 @@
+// 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.
+
+#include "ip.rsh"
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs
new file mode 100644
index 0000000..e706d44
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static float sr = 0.f;
+static float sg = 0.f;
+static float sb = 0.f;
+
+void prepareBwFilter(uint32_t rw, uint32_t gw, uint32_t bw) {
+
+    sr = rw;
+    sg = gw;
+    sb = bw;
+
+    float imageMin = min(sg,sb);
+    imageMin = fmin(sr,imageMin);
+    float imageMax = max(sg,sb);
+    imageMax = fmax(sr,imageMax);
+    float avg = (imageMin + imageMax)/2;
+    sb /= avg;
+    sg /= avg;
+    sr /= avg;
+
+}
+
+void bwFilterKernel(const uchar4 *in, uchar4 *out) {
+    float r = in->r * sr;
+    float g = in->g * sg;
+    float b = in->b * sb;
+    float localMin, localMax, avg;
+    localMin = fmin(g,b);
+    localMin = fmin(r,localMin);
+    localMax = fmax(g,b);
+    localMax = fmax(r,localMax);
+    avg = (localMin+localMax) * 0.5f;
+    out->r = out->g = out->b = rsClamp(avg, 0, 255);
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.fs
new file mode 100644
index 0000000..86fb248
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.fs
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static rs_matrix4x4 Mat;
+
+void init() {
+    rsMatrixLoadIdentity(&Mat);
+}
+
+void setMatrix(rs_matrix4x4 m) {
+    Mat = m;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    float4 f = convert_float4(in);
+    f = rsMatrixMultiply(&Mat, f);
+    f = clamp(f, 0.f, 255.f);
+    return convert_uchar4(f);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/contrast.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/contrast.rs
new file mode 100644
index 0000000..d3743d3
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/contrast.rs
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static float brightM = 0.f;
+static float brightC = 0.f;
+
+void setBright(float v) {
+    brightM = pow(2.f, v / 100.f);
+    brightC = 127.f - brightM * 127.f;
+}
+
+void contrast(const uchar4 *in, uchar4 *out)
+{
+#if 0
+    out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
+    out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
+    out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
+#else
+    float3 v = convert_float3(in->rgb) * brightM + brightC;
+    out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+#endif
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.fs
new file mode 100644
index 0000000..177e86e
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.fs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
+    p00 *= gCoeffs[0];
+    p01 *= gCoeffs[1];
+    p02 *= gCoeffs[2];
+    p10 *= gCoeffs[3];
+    p11 *= gCoeffs[4];
+    p12 *= gCoeffs[5];
+    p20 *= gCoeffs[6];
+    p21 *= gCoeffs[7];
+    p22 *= gCoeffs[8];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = clamp(p20, 0.f, 255.f);
+    return convert_uchar4(p20);
+}
+
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.fs
new file mode 100644
index 0000000..922a593
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.fs
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    return convert_uchar4(p0);
+}
+
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/copy.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/copy.fs
new file mode 100644
index 0000000..6595874
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/copy.fs
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    return v_in;
+}
+
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/exposure.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
new file mode 100644
index 0000000..0f05cb9
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+static float bright = 0.f;
+
+void setBright(float v) {
+    bright = 255.f / (255.f - v);
+}
+
+void exposure(const uchar4 *in, uchar4 *out)
+{
+    out->r = rsClamp((int)(bright * in->r), 0, 255);
+    out->g = rsClamp((int)(bright * in->g), 0, 255);
+    out->b = rsClamp((int)(bright * in->b), 0, 255);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye.rsh b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..2eacb7d
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx.rsh b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..fcf0a3d
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0f + 0.75f;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15f * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    return rsPackColorTo8888(fout);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..ed69ff4
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye_approx.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.fs
new file mode 100644
index 0000000..ed69ff4
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye_approx.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
new file mode 100644
index 0000000..f986b5d
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.fs
new file mode 100644
index 0000000..f986b5d
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "fisheye.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/grain.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/grain.fs
new file mode 100644
index 0000000..2e62cd7
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/grain.fs
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+uchar __attribute__((kernel)) genRand() {
+    return (uchar)rsRand(0xff);
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWMask;
+int32_t gHMask;
+
+rs_allocation gBlendSource;
+uchar __attribute__((kernel)) blend9(uint32_t x, uint32_t y) {
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
+
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = min(p20 >> 10, (uint)255);
+    return (uchar)p20;
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(in);
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    return p;
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/greyscale.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/greyscale.fs
new file mode 100644
index 0000000..4e13072
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/greyscale.fs
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+    float4 f4 = rsUnpackColor8888(v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    return rsPackColorTo8888(mono);
+}
+
+uchar __attribute__((kernel)) toU8(uchar4 v_in) {
+    float4 f4 = convert_float4(v_in);
+    return (uchar)dot(f4.rgb, gMonoMult);
+}
+
+uchar4 __attribute__((kernel)) toU8_4(uchar v_in) {
+    return (uchar4)v_in;
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/ip.rsh b/java/tests/ImageProcessing_jb/src/com/android/rs/image/ip.rsh
new file mode 100644
index 0000000..8124211
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/ip.rsh
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
+
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh b/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..e289906
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    uchar4 out;
+    float3 pixel = convert_float4(in).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out.xyz = convert_uchar3(pixel);
+    out.w = 0xff;
+    return out;
+}
+
+uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(in);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    return convert_uchar4(pixel);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
new file mode 100644
index 0000000..28596ba
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "levels.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.fs
new file mode 100644
index 0000000..28596ba
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "levels.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..de0bd00
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,55 @@
+// 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.
+
+#include "ip.rsh"
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    return (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.f;
+    if (iter <= (gMaxIteration / 3))
+      return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                      (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                      (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/msg.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/msg.rs
new file mode 100644
index 0000000..645eb98
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/msg.rs
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
+
+void sendMsg() {
+    rsSendToClientBlocking(0);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/shadows.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/shadows.rs
new file mode 100644
index 0000000..f6c149d
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/shadows.rs
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static double shadowFilterMap[] = {
+    -0.00591,  0.0001,
+     1.16488,  0.01668,
+    -0.18027, -0.06791,
+    -0.12625,  0.09001,
+     0.15065, -0.03897
+};
+
+static double poly[] = {
+    0., 0.,
+    0., 0.,
+    0.
+};
+
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static double fastevalPoly(double *poly,int n, double x){
+
+    double f =x;
+    double sum = poly[0]+poly[1]*f;
+    int i;
+    for (i = 2; i < n; i++) {
+        f*=x;
+        sum += poly[i]*f;
+    }
+    return sum;
+}
+
+static ushort3 rgb2hsv( uchar4 rgb)
+{
+    int iMin,iMax,chroma;
+
+    int ri = rgb.r;
+    int gi = rgb.g;
+    int bi = rgb.b;
+    short rv,rs,rh;
+
+    if (ri > gi) {
+        iMax = max (ri, bi);
+        iMin = min (gi, bi);
+    } else {
+        iMax = max (gi, bi);
+        iMin = min (ri, bi);
+    }
+
+    chroma = iMax - iMin;
+    // set value
+    rv = (short)( iMax << ABITS);
+
+    // set saturation
+    if (rv == 0)
+        rs = 0;
+    else
+        rs = (short)((k1*chroma)/iMax);
+
+    // set hue
+    if (rs == 0)
+        rh = 0;
+    else {
+        if ( ri == iMax ) {
+            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
+            if (rh >= k2) rh -= k2;
+        } else if (gi  == iMax)
+            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
+        else // (bi == iMax )
+                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
+    }
+
+    ushort3 out;
+    out.x = rv;
+    out.y = rs;
+    out.z = rh;
+    return out;
+}
+
+static uchar4 hsv2rgb(ushort3 hsv)
+{
+    int ABITS = 4;
+    int HSCALE = 256;
+    int m;
+    int H,X,ih,is,iv;
+    int k1=255<<ABITS;
+    int k2=HSCALE<<ABITS;
+    int k3=1<<(ABITS-1);
+    int rr=0;
+    int rg=0;
+    int rb=0;
+    short cv = hsv.x;
+    short cs = hsv.y;
+    short ch = hsv.z;
+
+    // set chroma and min component value m
+    //chroma = ( cv * cs )/k1;
+    //m = cv - chroma;
+    m = ((int)cv*(k1 - (int)cs ))/k1;
+
+    // chroma  == 0 <-> cs == 0 --> m=cv
+    if (cs == 0) {
+        rb = ( rg = ( rr =( cv >> ABITS) ));
+    } else {
+        ih=(int)ch;
+        is=(int)cs;
+        iv=(int)cv;
+
+        H = (6*ih)/k2;
+        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
+
+        // removing additional bits --> unit8
+        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
+        m=m >> ABITS;
+
+        // ( chroma + m ) --> cv ;
+        cv=(short) (cv >> ABITS);
+        switch (H) {
+        case 0:
+            rr = cv;
+            rg = X;
+            rb = m;
+            break;
+        case 1:
+            rr = X;
+            rg = cv;
+            rb = m;
+            break;
+        case 2:
+            rr = m;
+            rg = cv;
+            rb = X;
+            break;
+        case 3:
+            rr = m;
+            rg = X;
+            rb = cv;
+            break;
+        case 4:
+            rr = X;
+            rg = m;
+            rb = cv;
+            break;
+        case 5:
+            rr = cv;
+            rg = m ;
+            rb = X;
+            break;
+        }
+    }
+
+    uchar4 rgb;
+
+    rgb.r =  rr;
+    rgb.g =  rg;
+    rgb.b =  rb;
+
+    return rgb;
+}
+
+void prepareShadows(float scale) {
+    double s = (scale>=0)?scale:scale/5;
+    for (int i = 0; i < 5; i++) {
+        poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
+    }
+}
+
+void shadowsKernel(const uchar4 *in, uchar4 *out) {
+    ushort3 hsv = rgb2hsv(*in);
+    double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
+    if (v>4080) v = 4080;
+    hsv.x = (unsigned short) ((v>0)?v:0);
+    *out = hsv2rgb(hsv);
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/threshold.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/threshold.fs
new file mode 100644
index 0000000..0b2c2e8
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/threshold.fs
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+
+int height;
+int width;
+static int radius;
+
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+void setRadius(int rad) {
+    radius = rad;
+    // Compute gaussian weights for the blur
+    // e is the euler's number
+    float e = 2.718281828459045f;
+    float pi = 3.1415926535897932f;
+    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+    // x is of the form [-radius .. 0 .. radius]
+    // and sigma varies with radius.
+    // Based on some experimental radius values and sigma's
+    // we approximately fit sigma = f(radius) as
+    // sigma = radius * 0.4  + 0.6
+    // The larger the radius gets, the more our gaussian blur
+    // will resemble a box blur since with large sigma
+    // the gaussian curve begins to lose its shape
+    float sigma = 0.4f * (float)radius + 0.6f;
+
+    // Now compute the coefficints
+    // We will store some redundant values to save some math during
+    // the blur calculations
+    // precompute some values
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    //Now we need to normalize the weights because all our coefficients need to add up to one
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+float4 __attribute__((kernel)) copyIn(uchar4 in) {
+    return convert_float4(in);
+}
+
+uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    int gi = 0;
+    uchar4 out;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    }
+
+    out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out.w = 0xff;
+    return out;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    }
+
+    return blurredPixel;
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs
new file mode 100644
index 0000000..8db113c
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+float vibrance = 0.f;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+static float S  = 0.f;
+static float MS = 0.f;
+static float Rt = 0.f;
+static float Gt = 0.f;
+static float Bt = 0.f;
+static float Vib = 0.f;
+
+void vibranceKernel(const uchar4 *in, uchar4 *out) {
+
+    float R, G, B;
+
+    int r = in->r;
+    int g = in->g;
+    int b = in->b;
+    float red = (r-max(g, b))/256.f;
+    float sx = (float)(Vib/(1+exp(-red*3)));
+    S = sx+1;
+    MS = 1.0f - S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+    int t = (r + g) / 2;
+    R = r;
+    G = g;
+    B = b;
+
+    float Rc = R * (Rt + S) + G * Gt + B * Bt;
+    float Gc = R * Rt + G * (Gt + S) + B * Bt;
+    float Bc = R * Rt + G * Gt + B * (Bt + S);
+
+    out->r = rsClamp(Rc, 0, 255);
+    out->g = rsClamp(Gc, 0, 255);
+    out->b = rsClamp(Bc, 0, 255);
+
+}
+
+void prepareVibrance() {
+
+    Vib = vibrance/100.f;
+    S  = Vib + 1;
+    MS = 1.0f - S;
+    Rt = Rf * MS;
+    Gt = Gf * MS;
+    Bt = Bf * MS;
+
+}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
new file mode 100644
index 0000000..04ca1f1
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade / ( 1.0f + sloped_neg_range * exp(sloped_dist_ratio) );
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx.rsh b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..0eacdc8
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    return convert_uchar4(fout);
+}
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..00cbbc4
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette_approx.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.fs
new file mode 100644
index 0000000..00cbbc4
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette_approx.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
new file mode 100644
index 0000000..8202c5c
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.fs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.fs
new file mode 100644
index 0000000..8202c5c
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.fs
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+
+#include "vignette.rsh"
+
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs b/java/tests/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs
new file mode 100644
index 0000000..6650671
--- /dev/null
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
+
+rs_allocation histogramSource;
+uint32_t histogramHeight;
+uint32_t histogramWidth;
+
+static float scaleR;
+static float scaleG;
+static float scaleB;
+
+static uchar4 estimateWhite() {
+
+    for (int i = 0; i < 256; i++) {
+        histR[i] = 0; histG[i] = 0; histB[i] = 0;
+    }
+
+    for (uint32_t i = 0; i < histogramHeight; i++) {
+        for (uint32_t j = 0; j < histogramWidth; j++) {
+            uchar4 in = rsGetElementAt_uchar4(histogramSource, j, i);
+            histR[in.r]++;
+            histG[in.g]++;
+            histB[in.b]++;
+        }
+    }
+
+    int min_r = -1, min_g = -1, min_b = -1;
+    int max_r =  0, max_g =  0, max_b =  0;
+    int sum_r =  0, sum_g =  0, sum_b =  0;
+
+    for (int i = 1; i < 255; i++) {
+        int r = histR[i];
+        int g = histG[i];
+        int b = histB[i];
+        sum_r += r;
+        sum_g += g;
+        sum_b += b;
+
+        if (r>0){
+            if (min_r < 0) min_r = i;
+            max_r = i;
+        }
+        if (g>0){
+            if (min_g < 0) min_g = i;
+            max_g = i;
+        }
+        if (b>0){
+            if (min_b < 0) min_b = i;
+            max_b = i;
+        }
+    }
+
+    int sum15r = 0, sum15g = 0, sum15b = 0;
+    int count15r = 0, count15g = 0, count15b = 0;
+    int tmp_r = 0, tmp_g = 0, tmp_b = 0;
+
+    for (int i = 254; i >0; i--) {
+        int r = histR[i];
+        int g = histG[i];
+        int b = histB[i];
+        tmp_r += r;
+        tmp_g += g;
+        tmp_b += b;
+
+        if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
+            sum15r += r*i;
+            count15r += r;
+        }
+        if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
+            sum15g += g*i;
+            count15g += g;
+        }
+        if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
+            sum15b += b*i;
+            count15b += b;
+        }
+
+    }
+
+    uchar4 out;
+
+    if ((count15r>0) && (count15g>0) && (count15b>0) ){
+        out.r = sum15r/count15r;
+        out.g = sum15g/count15g;
+        out.b = sum15b/count15b;
+    }else {
+        out.r = out.g = out.b = 255;
+    }
+
+    return out;
+
+}
+
+void prepareWhiteBalance() {
+    uchar4 estimation = estimateWhite();
+    int minimum = min(estimation.r, min(estimation.g, estimation.b));
+    int maximum = max(estimation.r, max(estimation.g, estimation.b));
+    float avg = (minimum + maximum) / 2.f;
+
+    scaleR =  avg/estimation.r;
+    scaleG =  avg/estimation.g;
+    scaleB =  avg/estimation.b;
+
+}
+
+static unsigned char contrastClamp(int c)
+{
+    int N = 255;
+    c &= ~(c >> 31);
+    c -= N;
+    c &= (c >> 31);
+    c += N;
+    return  (unsigned char) c;
+}
+
+void whiteBalanceKernel(const uchar4 *in, uchar4 *out) {
+    float Rc =  in->r*scaleR;
+    float Gc =  in->g*scaleG;
+    float Bc =  in->b*scaleB;
+
+    out->r = contrastClamp(Rc);
+    out->g = contrastClamp(Gc);
+    out->b = contrastClamp(Bc);
+}
diff --git a/java/tests/LatencyBenchmark/Android.mk b/java/tests/LatencyBenchmark/Android.mk
new file mode 100644
index 0000000..ef2164d
--- /dev/null
+++ b/java/tests/LatencyBenchmark/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsLatencyBenchmark
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/LatencyBenchmark/AndroidManifest.xml b/java/tests/LatencyBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..923bb88
--- /dev/null
+++ b/java/tests/LatencyBenchmark/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.latencybench">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="_RS_Latency_Bench">
+        <activity android:name="LatencyBench">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/LatencyBenchmark/res/layout/main.xml b/java/tests/LatencyBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..9e9dab8
--- /dev/null
+++ b/java/tests/LatencyBenchmark/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/Benchmark.java b/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/Benchmark.java
new file mode 100644
index 0000000..ee14fb9
--- /dev/null
+++ b/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/Benchmark.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.example.android.rs.latencybench;
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class Benchmark implements Runnable {
+    private final RenderScript mRS;
+    private ScriptC_compute_benchmark mScript;
+    private Allocation ain;
+    private Allocation aout;
+
+    public Benchmark(RenderScript rs, Resources res) {
+        mRS = rs;
+        mScript = new ScriptC_compute_benchmark(mRS, res, R.raw.compute_benchmark);
+        ain = Allocation.createSized(rs, Element.U32(mRS), 10000);
+        aout = Allocation.createSized(rs, Element.U32(mRS), 10000);
+    }
+
+    public void run() {
+        int[] temp;
+        temp = new int[1];
+
+        long t = java.lang.System.currentTimeMillis();
+
+        for (int i = 0; i < 1000000; i++)
+            mScript.forEach_root(ain, aout);
+        aout.copy1DRangeFrom(0, 1, temp);
+
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("LatencyBench", "Iterated Java forEach took " + t + " ms");
+
+        mScript.set_empty_kern(mScript);
+        mScript.set_in(ain);
+        mScript.set_out(aout);
+
+        t = java.lang.System.currentTimeMillis();
+        mScript.invoke_emptyKernelLauncher();
+        aout.copy1DRangeFrom(0, 1, temp);
+
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("LatencyBench", "Invoked forEach took " + t + " ms");
+
+
+
+    }
+
+}
diff --git a/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/LatencyBench.java b/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/LatencyBench.java
new file mode 100644
index 0000000..fdce9a7
--- /dev/null
+++ b/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/LatencyBench.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.example.android.rs.latencybench;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+
+public class LatencyBench extends Activity {
+    private RenderScript mRS;
+    private Benchmark mBenchmark;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+
+        mBenchmark = new Benchmark(mRS, getResources());
+        mBenchmark.run();
+    }
+}
diff --git a/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs b/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
new file mode 100644
index 0000000..c6d1ea9
--- /dev/null
+++ b/java/tests/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
@@ -0,0 +1,29 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.latencybench)
+
+rs_script empty_kern;
+rs_allocation in, out;
+int iters = 1000000;
+
+void root(const uint32_t *ain, uint32_t *aout) {
+
+}
+
+void emptyKernelLauncher() {
+    for (int i = 0; i < iters; i++)
+        rsForEach(empty_kern, in, out);
+}
diff --git a/java/tests/LivePreview/Android.mk b/java/tests/LivePreview/Android.mk
new file mode 100644
index 0000000..1b45573
--- /dev/null
+++ b/java/tests/LivePreview/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := PreviewRS
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/LivePreview/AndroidManifest.xml b/java/tests/LivePreview/AndroidManifest.xml
new file mode 100644
index 0000000..1b91464
--- /dev/null
+++ b/java/tests/LivePreview/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.livepreview">
+    <uses-sdk android:minSdkVersion="14" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <application android:label="Preview FS"
+                 android:hardwareAccelerated="true">
+
+        <activity android:name="CameraPreviewActivity"
+                  android:label="Preview FS"
+                  android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/java/tests/LivePreview/res/drawable-nodpi/city.png b/java/tests/LivePreview/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..856eeff
--- /dev/null
+++ b/java/tests/LivePreview/res/drawable-nodpi/city.png
Binary files differ
diff --git a/java/tests/LivePreview/res/layout/cf_format_list_item.xml b/java/tests/LivePreview/res/layout/cf_format_list_item.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/java/tests/LivePreview/res/layout/cf_format_list_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/java/tests/LivePreview/res/layout/cf_main.xml b/java/tests/LivePreview/res/layout/cf_main.xml
new file mode 100644
index 0000000..ecb736b
--- /dev/null
+++ b/java/tests/LivePreview/res/layout/cf_main.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" >
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="3" >
+
+            <TextureView
+                android:id="@+id/preview_view"
+                android:layout_height="0dp"
+                android:layout_width="fill_parent"
+                android:layout_weight="3" />
+            <TextView
+                android:id="@+id/preview_label"
+                android:layout_height="wrap_content"
+                android:layout_width="fill_parent"
+                android:text="@string/cf_preview_label"
+                android:padding="2dp"
+                android:textSize="16sp"
+                android:gravity="center" />
+
+        </LinearLayout>
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="3" >
+
+            <TextureView
+                android:id="@+id/format_view"
+                android:layout_height="0dp"
+                android:layout_width="fill_parent"
+                android:layout_weight="3" />
+            <TextView
+                android:id="@+id/format_label"
+                android:layout_height="wrap_content"
+                android:layout_width="fill_parent"
+                android:text="@string/cf_format_label"
+                android:padding="2dp"
+                android:textSize="16sp"
+                android:gravity="center" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="2" >
+
+            <Spinner
+                android:id="@+id/cameras_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/resolution_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/format_selection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+
+</LinearLayout>
diff --git a/java/tests/LivePreview/res/layout/main.xml b/java/tests/LivePreview/res/layout/main.xml
new file mode 100644
index 0000000..a6a075c
--- /dev/null
+++ b/java/tests/LivePreview/res/layout/main.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/java/tests/LivePreview/res/layout/rs.xml b/java/tests/LivePreview/res/layout/rs.xml
new file mode 100644
index 0000000..6fde1b9
--- /dev/null
+++ b/java/tests/LivePreview/res/layout/rs.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <TextureView
+                android:id="@+id/display"
+                android:layout_width="800sp"
+                android:layout_height="423sp" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/java/tests/LivePreview/res/values/strings.xml b/java/tests/LivePreview/res/values/strings.xml
new file mode 100644
index 0000000..d651bfb
--- /dev/null
+++ b/java/tests/LivePreview/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+
+    <string name="app_name">CTS Verifier</string>
+    <string name="welcome_text">Welcome to the CTS Verifier!</string>
+    <string name="version_text">%1$s</string>
+    <string name="continue_button_text">Continue</string>
+
+    <string name="cf_preview_label">Normal preview</string>
+    <string name="cf_format_label">Processed callback data</string>
+    <string name="camera_format">Camera Formats</string>
+
+
+</resources>
diff --git a/java/tests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java b/java/tests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
new file mode 100644
index 0000000..62dcaa8
--- /dev/null
+++ b/java/tests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
@@ -0,0 +1,374 @@
+/*
+ * 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 com.android.rs.livepreview;
+
+//import com.android.cts.verifier.PassFailButtons;
+//import com.android.cts.verifier.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.TextureView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.Spinner;
+
+import java.io.IOException;
+import java.lang.InterruptedException;
+import java.lang.Math;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeSet;
+
+import android.renderscript.*;
+
+/**
+ * Tests for manual verification of the CDD-required camera output formats
+ * for preview callbacks
+ */
+public class CameraPreviewActivity extends Activity
+        implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
+
+    private static final String TAG = "CameraFormats";
+
+    private TextureView mPreviewView;
+    private SurfaceTexture mPreviewTexture;
+    private int mPreviewTexWidth;
+    private int mPreviewTexHeight;
+
+    //private TextureView mFormatView;
+
+    private Spinner mCameraSpinner;
+    private Spinner mResolutionSpinner;
+
+    private int mCurrentCameraId = -1;
+    private Camera mCamera;
+
+    private List<Camera.Size> mPreviewSizes;
+    private Camera.Size mNextPreviewSize;
+    private Camera.Size mPreviewSize;
+
+    private TextureView mOutputView;
+    //private Bitmap mCallbackBitmap;
+
+    private static final int STATE_OFF = 0;
+    private static final int STATE_PREVIEW = 1;
+    private static final int STATE_NO_CALLBACKS = 2;
+    private int mState = STATE_OFF;
+    private boolean mProcessInProgress = false;
+    private boolean mProcessingFirstFrame = false;
+
+
+    private RenderScript mRS;
+    private RsYuv mFilterYuv;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.cf_main);
+
+        mPreviewView = (TextureView) findViewById(R.id.preview_view);
+        mOutputView = (TextureView) findViewById(R.id.format_view);
+
+        mPreviewView.setSurfaceTextureListener(this);
+
+        int numCameras = Camera.getNumberOfCameras();
+        String[] cameraNames = new String[numCameras];
+        for (int i = 0; i < numCameras; i++) {
+            cameraNames[i] = "Camera " + i;
+        }
+        mCameraSpinner = (Spinner) findViewById(R.id.cameras_selection);
+        mCameraSpinner.setAdapter(
+            new ArrayAdapter<String>(
+                this, R.layout.cf_format_list_item, cameraNames));
+        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
+
+        mResolutionSpinner = (Spinner) findViewById(R.id.resolution_selection);
+        mResolutionSpinner.setOnItemSelectedListener(mResolutionSelectedListener);
+
+        mRS = RenderScript.create(this);
+        mFilterYuv = new RsYuv(mRS);
+        mOutputView.setSurfaceTextureListener(mFilterYuv);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        setUpCamera(mCameraSpinner.getSelectedItemPosition());
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        shutdownCamera();
+    }
+
+    public void onSurfaceTextureAvailable(SurfaceTexture surface,
+            int width, int height) {
+        mPreviewTexture = surface;
+        mPreviewTexWidth = width;
+        mPreviewTexHeight = height;
+        if (mCamera != null) {
+            startPreview();
+        }
+    }
+
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        // Ignored, Camera does all the work for us
+    }
+
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        return true;
+    }
+
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        // Invoked every time there's a new Camera preview frame
+    }
+
+    private AdapterView.OnItemSelectedListener mCameraSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent,
+                        View view, int pos, long id) {
+                    if (mCurrentCameraId != pos) {
+                        setUpCamera(pos);
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+
+            };
+
+    private AdapterView.OnItemSelectedListener mResolutionSelectedListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent,
+                        View view, int position, long id) {
+                    if (mPreviewSizes.get(position) != mPreviewSize) {
+                        mNextPreviewSize = mPreviewSizes.get(position);
+                        startPreview();
+                    }
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+
+            };
+
+
+    private void setUpCamera(int id) {
+        shutdownCamera();
+
+        mCurrentCameraId = id;
+        mCamera = Camera.open(id);
+        Camera.Parameters p = mCamera.getParameters();
+
+        // Get preview resolutions
+
+        List<Camera.Size> unsortedSizes = p.getSupportedPreviewSizes();
+
+        class SizeCompare implements Comparator<Camera.Size> {
+            public int compare(Camera.Size lhs, Camera.Size rhs) {
+                if (lhs.width < rhs.width) return -1;
+                if (lhs.width > rhs.width) return 1;
+                if (lhs.height < rhs.height) return -1;
+                if (lhs.height > rhs.height) return 1;
+                return 0;
+            }
+        };
+
+        SizeCompare s = new SizeCompare();
+        TreeSet<Camera.Size> sortedResolutions = new TreeSet<Camera.Size>(s);
+        sortedResolutions.addAll(unsortedSizes);
+
+        mPreviewSizes = new ArrayList<Camera.Size>(sortedResolutions);
+
+        String[] availableSizeNames = new String[mPreviewSizes.size()];
+        for (int i = 0; i < mPreviewSizes.size(); i++) {
+            availableSizeNames[i] =
+                    Integer.toString(mPreviewSizes.get(i).width) + " x " +
+                    Integer.toString(mPreviewSizes.get(i).height);
+        }
+        mResolutionSpinner.setAdapter(
+            new ArrayAdapter<String>(
+                this, R.layout.cf_format_list_item, availableSizeNames));
+
+
+        // Set initial values
+
+        mNextPreviewSize = mPreviewSizes.get(15);
+        mResolutionSpinner.setSelection(15);
+
+        if (mPreviewTexture != null) {
+            startPreview();
+        }
+    }
+
+    private void shutdownCamera() {
+        if (mCamera != null) {
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+            mCamera.release();
+            mCamera = null;
+            mState = STATE_OFF;
+        }
+    }
+
+    private void startPreview() {
+        if (mState != STATE_OFF) {
+            // Stop for a while to drain callbacks
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+            mState = STATE_OFF;
+            Handler h = new Handler();
+            Runnable mDelayedPreview = new Runnable() {
+                public void run() {
+                    startPreview();
+                }
+            };
+            h.postDelayed(mDelayedPreview, 300);
+            return;
+        }
+        mState = STATE_PREVIEW;
+
+        Matrix transform = new Matrix();
+        float widthRatio = mNextPreviewSize.width / (float)mPreviewTexWidth;
+        float heightRatio = mNextPreviewSize.height / (float)mPreviewTexHeight;
+
+        transform.setScale(1, heightRatio/widthRatio);
+        transform.postTranslate(0,
+                mPreviewTexHeight * (1 - heightRatio/widthRatio)/2);
+
+        mPreviewView.setTransform(transform);
+        mOutputView.setTransform(transform);
+
+        mPreviewSize   = mNextPreviewSize;
+
+        Camera.Parameters p = mCamera.getParameters();
+        p.setPreviewFormat(ImageFormat.NV21);
+        p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+        mCamera.setParameters(p);
+
+        mCamera.setPreviewCallbackWithBuffer(this);
+        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
+                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
+        for (int i=0; i < 4; i++) {
+            mCamera.addCallbackBuffer(new byte[expectedBytes]);
+        }
+        //mFormatView.setColorFilter(mYuv2RgbFilter);
+
+        mProcessingFirstFrame = true;
+        try {
+            mCamera.setPreviewTexture(mPreviewTexture);
+            mCamera.startPreview();
+        } catch (IOException ioe) {
+            // Something bad happened
+            Log.e(TAG, "Unable to start up preview");
+        }
+
+    }
+
+
+    private class ProcessPreviewDataTask extends AsyncTask<byte[], Void, Boolean> {
+        protected Boolean doInBackground(byte[]... datas) {
+            byte[] data = datas[0];
+
+            long t1 = java.lang.System.currentTimeMillis();
+
+            mFilterYuv.execute(data);
+
+            long t2 = java.lang.System.currentTimeMillis();
+            mTiming[mTimingSlot++] = t2 - t1;
+            if (mTimingSlot >= mTiming.length) {
+                float total = 0;
+                for (int i=0; i<mTiming.length; i++) {
+                    total += (float)mTiming[i];
+                }
+                total /= mTiming.length;
+                Log.e(TAG, "time + " + total);
+                mTimingSlot = 0;
+            }
+
+            mCamera.addCallbackBuffer(data);
+            mProcessInProgress = false;
+            return true;
+        }
+
+        protected void onPostExecute(Boolean result) {
+            mOutputView.invalidate();
+        }
+
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    public void onPreviewFrame(byte[] data, Camera camera) {
+        if (mProcessInProgress || mState != STATE_PREVIEW) {
+            mCamera.addCallbackBuffer(data);
+            return;
+        }
+        if (data == null) {
+            return;
+        }
+
+        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
+                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
+
+        if (expectedBytes != data.length) {
+            Log.e(TAG, "Mismatched size of buffer! Expected ");
+
+            mState = STATE_NO_CALLBACKS;
+            mCamera.setPreviewCallbackWithBuffer(null);
+            return;
+        }
+
+        mProcessInProgress = true;
+
+        if ((mFilterYuv == null) ||
+            (mPreviewSize.width != mFilterYuv.getWidth()) ||
+            (mPreviewSize.height != mFilterYuv.getHeight()) ) {
+
+            mFilterYuv.reset(mPreviewSize.width, mPreviewSize.height);
+        }
+
+        mProcessInProgress = true;
+        new ProcessPreviewDataTask().execute(data);
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/java/tests/LivePreview/src/com/android/rs/livepreview/RsYuv.java b/java/tests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
new file mode 100644
index 0000000..12d3185
--- /dev/null
+++ b/java/tests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
@@ -0,0 +1,151 @@
+/*
+ * 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 com.android.rs.livepreview;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.graphics.SurfaceTexture;
+import android.renderscript.Allocation;
+import android.renderscript.Matrix3f;
+import android.renderscript.RenderScript;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+import android.graphics.Bitmap;
+
+public class RsYuv implements TextureView.SurfaceTextureListener
+{
+    private int mHeight;
+    private int mWidth;
+    private RenderScript mRS;
+    private Allocation mAllocationOut;
+    private Allocation mAllocationIn;
+    private ScriptC_yuv mScript;
+    private ScriptIntrinsicYuvToRGB mYuv;
+    private boolean mHaveSurface;
+    private SurfaceTexture mSurface;
+    private ScriptGroup mGroup;
+
+    RsYuv(RenderScript rs) {
+        mRS = rs;
+        mScript = new ScriptC_yuv(mRS);
+        mYuv = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(mRS));
+    }
+
+    void setupSurface() {
+        if (mAllocationOut != null) {
+            mAllocationOut.setSurfaceTexture(mSurface);
+        }
+        if (mSurface != null) {
+            mHaveSurface = true;
+        } else {
+            mHaveSurface = false;
+        }
+    }
+
+    void reset(int width, int height) {
+        if (mAllocationOut != null) {
+            mAllocationOut.destroy();
+        }
+
+        android.util.Log.v("cpa", "reset " + width + ", " + height);
+        mHeight = height;
+        mWidth = width;
+        mScript.invoke_setSize(mWidth, mHeight);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        Type t = tb.create();
+        mAllocationOut = Allocation.createTyped(mRS, t, Allocation.USAGE_SCRIPT |
+                                                        Allocation.USAGE_IO_OUTPUT);
+
+
+        tb = new Type.Builder(mRS, Element.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV));
+        tb.setX(mWidth);
+        tb.setY(mHeight);
+        tb.setYuvFormat(android.graphics.ImageFormat.NV21);
+        mAllocationIn = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
+        mYuv.setInput(mAllocationIn);
+        setupSurface();
+
+
+        ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+        b.addKernel(mScript.getKernelID_root());
+        b.addKernel(mYuv.getKernelID());
+        b.addConnection(t, mYuv.getKernelID(), mScript.getKernelID_root());
+        mGroup = b.create();
+    }
+
+    public int getWidth() {
+        return mWidth;
+    }
+    public int getHeight() {
+        return mHeight;
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    void execute(byte[] yuv) {
+        mAllocationIn.copyFrom(yuv);
+        if (mHaveSurface) {
+            mGroup.setOutput(mScript.getKernelID_root(), mAllocationOut);
+            mGroup.execute();
+
+            //mYuv.forEach(mAllocationOut);
+            //mScript.forEach_root(mAllocationOut, mAllocationOut);
+            mAllocationOut.ioSendOutput();
+        }
+    }
+
+
+
+    @Override
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        android.util.Log.v("cpa", "onSurfaceTextureAvailable " + surface);
+        mSurface = surface;
+        setupSurface();
+    }
+
+    @Override
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        android.util.Log.v("cpa", "onSurfaceTextureSizeChanged " + surface);
+        mSurface = surface;
+        setupSurface();
+    }
+
+    @Override
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        android.util.Log.v("cpa", "onSurfaceTextureDestroyed " + surface);
+        mSurface = surface;
+        setupSurface();
+        return true;
+    }
+
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+    }
+}
+
diff --git a/java/tests/LivePreview/src/com/android/rs/livepreview/yuv.rs b/java/tests/LivePreview/src/com/android/rs/livepreview/yuv.rs
new file mode 100644
index 0000000..c4f698f
--- /dev/null
+++ b/java/tests/LivePreview/src/com/android/rs/livepreview/yuv.rs
@@ -0,0 +1,126 @@
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.livepreview)
+//#pragma rs_fp_relaxed
+
+static int gWidth;
+static int gHeight;
+static uchar crossProcess_tableR[256];
+static uchar crossProcess_tableG[256];
+static uchar crossProcess_tableB[256];
+static uchar vignette_table[512];
+
+
+static float4 crossProcess(float4 color) {
+    float4 ncolor = 0.f;
+    float v;
+
+    if (color.r < 0.5f) {
+        v = color.r;
+        ncolor.r = 4.0f * v * v * v;
+    } else {
+        v = 1.0f - color.r;
+        ncolor.r = 1.0f - (4.0f * v * v * v);
+    }
+
+    if (color.g < 0.5f) {
+        v = color.g;
+        ncolor.g = 2.0f * v * v;
+    } else {
+        v = 1.0f - color.g;
+        ncolor.g = 1.0f - (2.0f * v * v);
+    }
+
+    ncolor.b = color.b * 0.5f + 0.25f;
+    ncolor.a = color.a;
+    return ncolor;
+}
+
+static uchar4 crossProcess_i(uchar4 color) {
+    uchar4 ncolor = color;
+    ncolor.r = crossProcess_tableR[color.r];
+    ncolor.g = crossProcess_tableG[color.g];
+    ncolor.b = crossProcess_tableB[color.b];
+    return ncolor;
+}
+
+
+float temp = 0.2f;
+static float4 colortemp(float4 color) {
+    float4 new_color = color;
+    float4 t = color * ((float4)1.0f - color) * temp;
+
+    new_color.r = color.r + t.r;
+    new_color.b = color.b - t.b;
+    if (temp > 0.0f) {
+        color.g = color.g + t.g * 0.25f;
+    }
+    float max_value = max(new_color.r, max(new_color.g, new_color.b));
+    if (max_value > 1.0f) {
+        new_color /= max_value;
+    }
+
+    return new_color;
+}
+
+
+static float vignette_dist_mod;
+int2 vignette_half_dims;
+static uchar4 vignette(uchar4 color, uint32_t x, uint32_t y) {
+    int2 xy = {x, y};
+    xy -= vignette_half_dims;
+    xy *= xy;
+
+    float d = vignette_dist_mod * (xy.x + xy.y);
+    ushort4 c = convert_ushort4(color);
+    c *= vignette_table[(int)d];
+    c >>= (ushort4)8;
+    return convert_uchar4(c);
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    uchar4 p;
+    p = crossProcess_i(*in);
+    p = vignette(p, x, y);
+
+    out->rgba = p;
+    out->a = 0xff;
+}
+
+float vignetteScale = 0.5f;
+float vignetteShade = 0.85f;
+
+static void precompute() {
+    for(int i=0; i <256; i++) {
+        float4 f = ((float)i) / 255.f;
+        float4 res = crossProcess(f);
+        res = colortemp(res);
+        crossProcess_tableR[i] = (uchar)(res.r * 255.f);
+        crossProcess_tableG[i] = (uchar)(res.g * 255.f);
+        crossProcess_tableB[i] = (uchar)(res.b * 255.f);
+    }
+
+    for(int i=0; i <512; i++) {
+        const float slope = 20.0f;
+        float f = ((float)i) / 511.f;
+
+        float range = 1.30f - sqrt(vignetteScale) * 0.7f;
+        float lumen = vignetteShade / (1.0f + exp((sqrt(f) - range) * slope)) + (1.0f - vignetteShade);
+        lumen = clamp(lumen, 0.f, 1.f);
+
+        vignette_table[i] = (uchar)(lumen * 255.f + 0.5f);
+    }
+}
+
+void init() {
+    precompute();
+}
+
+void setSize(int w, int h) {
+    gWidth = w;
+    gHeight = h;
+    vignette_half_dims = (int2){w / 2, h / 2};
+    vignette_dist_mod = 512.f;
+    vignette_dist_mod /= (float)(w*w + h*h) / 4.f;
+
+}
diff --git a/java/tests/MathErr/Android.mk b/java/tests/MathErr/Android.mk
new file mode 100644
index 0000000..b3edd02
--- /dev/null
+++ b/java/tests/MathErr/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsMathErr
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/MathErr/AndroidManifest.xml b/java/tests/MathErr/AndroidManifest.xml
new file mode 100644
index 0000000..6a3db2c
--- /dev/null
+++ b/java/tests/MathErr/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.matherr">
+
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="RS Math Err">
+        <activity android:name="MathErrActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/MathErr/res/layout/main.xml b/java/tests/MathErr/res/layout/main.xml
new file mode 100644
index 0000000..7b2c76a
--- /dev/null
+++ b/java/tests/MathErr/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/java/tests/MathErr/src/com/example/android/rs/matherr/MathErr.java b/java/tests/MathErr/src/com/example/android/rs/matherr/MathErr.java
new file mode 100644
index 0000000..4561267
--- /dev/null
+++ b/java/tests/MathErr/src/com/example/android/rs/matherr/MathErr.java
@@ -0,0 +1,86 @@
+/*
+ * 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 com.example.android.rs.matherr;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import java.lang.Float;
+import java.lang.Math;
+
+public class MathErr {
+    private RenderScript mRS;
+    private Allocation mAllocationSrc;
+    private Allocation mAllocationRes;
+    private ScriptC_math_err mScript;
+    private java.util.Random mRand = new java.util.Random();
+
+    private final int BUF_SIZE = 4096;
+    float mSrc[] = new float[BUF_SIZE];
+    float mRef[] = new float[BUF_SIZE];
+    float mRes[] = new float[BUF_SIZE];
+
+    MathErr(RenderScript rs) {
+        mRS = rs;
+        mScript = new ScriptC_math_err(mRS);
+
+        mAllocationSrc = Allocation.createSized(rs, Element.F32(rs), BUF_SIZE);
+        mAllocationRes = Allocation.createSized(rs, Element.F32(rs), BUF_SIZE);
+
+        testExp2();
+        testLog2();
+    }
+
+    void buildRand() {
+        for (int i=0; i < BUF_SIZE; i++) {
+            mSrc[i] = (((float)i) / 9) - 200;
+            //mSrc[i] = Float.intBitsToFloat(mRand.nextInt());
+        }
+        mAllocationSrc.copyFrom(mSrc);
+    }
+
+    void logErr() {
+        mAllocationRes.copyTo(mRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            int err = Float.floatToRawIntBits(mRef[i]) - Float.floatToRawIntBits(mRes[i]);
+            err = Math.abs(err);
+            if (err > 8096) {
+                android.util.Log.v("err", "error " + err + " src " + mSrc[i] + " ref " + mRef[i] + " res " + mRes[i]);
+            }
+        }
+    }
+
+    void testExp2() {
+        android.util.Log.v("err", "testing exp2");
+        buildRand();
+        mScript.forEach_testExp2(mAllocationSrc, mAllocationRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            mRef[i] = (float)Math.pow(2.f, mSrc[i]);
+        }
+        logErr();
+    }
+
+    void testLog2() {
+        android.util.Log.v("err", "testing log2");
+        buildRand();
+        mScript.forEach_testLog2(mAllocationSrc, mAllocationRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            mRef[i] = (float)Math.log(mSrc[i]) * 1.442695041f;
+        }
+        logErr();
+    }
+
+}
diff --git a/java/tests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java b/java/tests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java
new file mode 100644
index 0000000..74d7b71
--- /dev/null
+++ b/java/tests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.example.android.rs.matherr;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.util.Log;
+
+public class MathErrActivity extends Activity {
+    private MathErr mME;
+    private RenderScript mRS;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+        mME = new MathErr(mRS);
+    }
+}
diff --git a/java/tests/MathErr/src/com/example/android/rs/matherr/math_err.rs b/java/tests/MathErr/src/com/example/android/rs/matherr/math_err.rs
new file mode 100644
index 0000000..a26770b
--- /dev/null
+++ b/java/tests/MathErr/src/com/example/android/rs/matherr/math_err.rs
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.matherr)
+
+typedef union
+{
+  float fv;
+  int32_t iv;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float.  */
+
+#define GET_FLOAT_WORD(i,d)         \
+do {                                \
+  ieee_float_shape_type gf_u;       \
+  gf_u.fv = (d);                    \
+  (i) = gf_u.iv;                    \
+} while (0)
+
+/* Set a float from a 32 bit int.  */
+
+#define SET_FLOAT_WORD(d,i)         \
+do {                                \
+  ieee_float_shape_type sf_u;       \
+  sf_u.iv = (i);                    \
+  (d) = sf_u.fv;                    \
+} while (0)
+
+
+static float fast_log2(float v) {
+    int32_t ibits;
+    GET_FLOAT_WORD(ibits, v);
+
+    int32_t e = (ibits >> 23) & 0xff;
+
+    ibits &= 0x7fffff;
+    ibits |= 127 << 23;
+
+    float ir;
+    SET_FLOAT_WORD(ir, ibits);
+
+    ir -= 1.5f;
+    float ir2 = ir*ir;
+    float adj2 = 0.405465108f + // -0.00009f +
+                 (0.666666667f * ir) -
+                 (0.222222222f * ir2) +
+                 (0.098765432f * ir*ir2) -
+                 (0.049382716f * ir2*ir2) +
+                 (0.026337449f * ir*ir2*ir2) -
+                 (0.014631916f * ir2*ir2*ir2);
+    adj2 *= (1.f / 0.693147181f);
+
+    return (float)(e - 127) + adj2;
+}
+
+void testExp2(const float *in, float *out) {
+    float i = *in;
+    if (i > (-125.f) && i < 125.f) {
+        *out = native_exp2(i);
+    } else {
+        *out = exp2(i);
+    }
+    *out = native_exp2(i);
+}
+
+void testLog2(const float *in, float *out) {
+    *out = fast_log2(*in);
+}
+
diff --git a/java/tests/RSTest_CompatLib/Android.mk b/java/tests/RSTest_CompatLib/Android.mk
new file mode 100644
index 0000000..0fd0d96
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/Android.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RSTest_Compat
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.support.v8.renderscript
+
+LOCAL_SDK_VERSION := 8
+LOCAL_RENDERSCRIPT_TARGET_API := 18
+LOCAL_RENDERSCRIPT_COMPATIBILITY := 18
+
+LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := \
+    $(TOPDIR)external/clang/lib/Headers \
+    $(TOPDIR)frameworks/rs/scriptc
+
+LOCAL_RENDERSCRIPT_FLAGS := -rs-package-name=android.support.v8.renderscript
+LOCAL_REQUIRED_MODULES := librsjni
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/RSTest_CompatLib/AndroidManifest.xml b/java/tests/RSTest_CompatLib/AndroidManifest.xml
new file mode 100644
index 0000000..53219e7
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.test_compat">
+  <uses-sdk android:minSdkVersion="8" />
+  <uses-sdk android:targetSdkVersion="8" />
+    <application
+        android:label="_RS_Test_Compat"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="RSTest"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png b/java/tests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java
new file mode 100644
index 0000000..b76f21e
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.support.v8.renderscript.RenderScript;
+
+import android.app.ListActivity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.ArrayAdapter;
+
+import java.lang.Runtime;
+
+public class RSTest extends ListActivity {
+
+    private static final String LOG_TAG = "RSTest_Compat";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private RenderScript mRS;
+    private RSTestCore RSTC;
+
+    String mTestNames[];
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mRS = RenderScript.create(this);
+
+        RSTC = new RSTestCore(this);
+        RSTC.init(mRS, getResources());
+
+
+
+
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java
new file mode 100644
index 0000000..51f8a4d
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008-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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.app.ListActivity;
+import android.widget.ArrayAdapter;
+
+public class RSTestCore {
+    ListActivity mCtx;
+
+    public RSTestCore(ListActivity ctx) {
+        mCtx = ctx;
+    }
+
+    private Resources mRes;
+    private RenderScript mRS;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    private ScriptField_ListAllocs_s mListAllocs;
+
+    private ArrayAdapter<UnitTest> testAdapter;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScript rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        stopTesting = false;
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_constant(this, mRes, mCtx));
+        unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_unsigned(this, mRes, mCtx));
+        unitTests.add(new UT_array_init(this, mRes, mCtx));
+        unitTests.add(new UT_array_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_kernel(this, mRes, mCtx));
+        unitTests.add(new UT_kernel_struct(this, mRes, mCtx));
+        unitTests.add(new UT_bug_char(this, mRes, mCtx));
+        unitTests.add(new UT_clamp(this, mRes, mCtx));
+        unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_convert(this, mRes, mCtx));
+        unitTests.add(new UT_convert_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_copy_test(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_refcount(this, mRes, mCtx));
+        unitTests.add(new UT_foreach(this, mRes, mCtx));
+        unitTests.add(new UT_foreach_bounds(this, mRes, mCtx));
+        unitTests.add(new UT_noroot(this, mRes, mCtx));
+        unitTests.add(new UT_atomic(this, mRes, mCtx));
+        unitTests.add(new UT_struct(this, mRes, mCtx));
+        unitTests.add(new UT_math(this, mRes, mCtx));
+        unitTests.add(new UT_math_conformance(this, mRes, mCtx));
+        unitTests.add(new UT_math_agree(this, mRes, mCtx));
+        unitTests.add(new UT_min(this, mRes, mCtx));
+        unitTests.add(new UT_int4(this, mRes, mCtx));
+        unitTests.add(new UT_element(this, mRes, mCtx));
+        unitTests.add(new UT_sampler(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
+
+        /*
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
+        unitTests.add(new UnitTest());
+        unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+        for (int i = 0; i < 20; i++) {
+            unitTests.add(new UnitTest(null, "<Pass>", 1));
+        }
+        */
+
+        UnitTest [] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].getResult();
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+
+        testAdapter = new ArrayAdapter<UnitTest>(mCtx, android.R.layout.simple_list_item_1, unitTests);
+        mCtx.setListAdapter(testAdapter);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        mCtx.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (testAdapter != null)
+                        testAdapter.notifyDataSetChanged();
+                }
+            });
+
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                }
+                catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            }
+            else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
new file mode 100644
index 0000000..3af3745
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Alloc", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_alloc s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        int Z = 0;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        s.set_dimZ(Z);
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+        s.set_aRaw(A);
+
+        typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        typeBuilder.setX(X).setY(Y).setFaces(true);
+        Allocation AFaces = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFaces(AFaces);
+        typeBuilder.setFaces(false).setMipmaps(true);
+        Allocation ALOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aLOD(ALOD);
+        typeBuilder.setFaces(true).setMipmaps(true);
+        Allocation AFacesLOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFacesLOD(AFacesLOD);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_alloc s = new ScriptC_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(s.get_aRaw());
+        s.invoke_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java
new file mode 100644
index 0000000..751187b
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java
@@ -0,0 +1,52 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_array_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Allocation", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_alloc s = new ScriptC_array_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        int dimX = s.get_dimX();
+        Allocation[] Arr = new Allocation[dimX];
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.I32(pRS));
+        Type T = typeBuilder.setX(1).create();
+        for (int i = 0; i < dimX; i++) {
+            Allocation A = Allocation.createTyped(pRS, T);
+            Arr[i] = A;
+        }
+        s.set_a(Arr);
+
+        s.invoke_array_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java
new file mode 100644
index 0000000..f8b2fd3
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java
@@ -0,0 +1,95 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_array_init extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_init(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Init", ctx);
+        mRes = res;
+    }
+
+    private void checkInit(ScriptC_array_init s) {
+        float[] fa = s.get_fa();
+        _RS_ASSERT("fa[0] == 1.0", fa[0] == 1.0);
+        _RS_ASSERT("fa[1] == 9.9999f", fa[1] == 9.9999f);
+        _RS_ASSERT("fa[2] == 0", fa[2] == 0);
+        _RS_ASSERT("fa[3] == 0", fa[3] == 0);
+        _RS_ASSERT("fa.length == 4", fa.length == 4);
+
+        double[] da = s.get_da();
+        _RS_ASSERT("da[0] == 7.0", da[0] == 7.0);
+        _RS_ASSERT("da[1] == 8.88888", da[1] == 8.88888);
+        _RS_ASSERT("da.length == 2", da.length == 2);
+
+        byte[] ca = s.get_ca();
+        _RS_ASSERT("ca[0] == 'a'", ca[0] == 'a');
+        _RS_ASSERT("ca[1] == 7", ca[1] == 7);
+        _RS_ASSERT("ca[2] == 'b'", ca[2] == 'b');
+        _RS_ASSERT("ca[3] == 'c'", ca[3] == 'c');
+        _RS_ASSERT("ca.length == 4", ca.length == 4);
+
+        short[] sa = s.get_sa();
+        _RS_ASSERT("sa[0] == 1", sa[0] == 1);
+        _RS_ASSERT("sa[1] == 1", sa[1] == 1);
+        _RS_ASSERT("sa[2] == 2", sa[2] == 2);
+        _RS_ASSERT("sa[3] == 3", sa[3] == 3);
+        _RS_ASSERT("sa.length == 4", sa.length == 4);
+
+        int[] ia = s.get_ia();
+        _RS_ASSERT("ia[0] == 5", ia[0] == 5);
+        _RS_ASSERT("ia[1] == 8", ia[1] == 8);
+        _RS_ASSERT("ia[2] == 0", ia[2] == 0);
+        _RS_ASSERT("ia[3] == 0", ia[3] == 0);
+        _RS_ASSERT("ia.length == 4", ia.length == 4);
+
+        long[] la = s.get_la();
+        _RS_ASSERT("la[0] == 13", la[0] == 13);
+        _RS_ASSERT("la[1] == 21", la[1] == 21);
+        _RS_ASSERT("la.length == 4", la.length == 2);
+
+        long[] lla = s.get_lla();
+        _RS_ASSERT("lla[0] == 34", lla[0] == 34);
+        _RS_ASSERT("lla[1] == 0", lla[1] == 0);
+        _RS_ASSERT("lla[2] == 0", lla[2] == 0);
+        _RS_ASSERT("lla[3] == 0", lla[3] == 0);
+        _RS_ASSERT("lla.length == 4", lla.length == 4);
+
+        boolean[] ba = s.get_ba();
+        _RS_ASSERT("ba[0] == true", ba[0] == true);
+        _RS_ASSERT("ba[1] == false", ba[1] == false);
+        _RS_ASSERT("ba[2] == false", ba[2] == false);
+        _RS_ASSERT("ba.length == 3", ba.length == 3);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_init s = new ScriptC_array_init(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        checkInit(s);
+        s.invoke_array_init_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java
new file mode 100644
index 0000000..7fe4b36
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_atomic extends UnitTest {
+    private Resources mRes;
+
+    protected UT_atomic(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Atomics", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_atomic s = new ScriptC_atomic(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_atomic_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java
new file mode 100644
index 0000000..5da5288
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java
@@ -0,0 +1,89 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+
+public class UT_bug_char extends UnitTest {
+    private Resources mRes;
+
+    protected UT_bug_char(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Bug Char", ctx);
+        mRes = res;
+    }
+
+    // packing functions
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        Log.i("bug_char", "pack_b2 " + val[0] + " " + val[1]);
+        return new Byte2(val[0], val[1]);
+    }
+
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_bug_char s) {
+        byte rand_sc1_0 = (byte)7;
+        byte[] rand_sc2_0 = new byte[2];
+        rand_sc2_0[0] = 11;
+        rand_sc2_0[1] = 21;
+        Log.i("bug_char", "Generated sc2_0 to " + Arrays.toString(rand_sc2_0));
+        byte rand_sc1_1 = (byte)10;
+        byte[] rand_sc2_1 = new byte[2];
+        rand_sc2_1[0] = 13;
+        rand_sc2_1[1] = 15;
+        Log.i("bug_char", "Generated sc2_1 to " + Arrays.toString(rand_sc2_1));
+
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        // Set results for min
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        byte[] min_rand_sc2_raw = min(rand_sc2_0, rand_sc2_1);
+        Log.i("bug_char", "Generating min_rand_sc2_sc2 to " +
+              Arrays.toString(min_rand_sc2_raw));
+        Byte2 min_rand_sc2 = pack_b2(min_rand_sc2_raw);
+        Log.i("bug_char", "Setting min_rand_sc2_sc2 to [" + min_rand_sc2.x +
+              ", " + min_rand_sc2.y + "]");
+        s.set_min_rand_sc2_sc2(min_rand_sc2);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_bug_char s = new ScriptC_bug_char(pRS, mRes,
+                R.raw.bug_char);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_bug_char_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java
new file mode 100644
index 0000000..1f28abc
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_clamp extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Full)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp s = new ScriptC_clamp(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java
new file mode 100644
index 0000000..d880e68
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_clamp_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp_relaxed s =
+                new ScriptC_clamp_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java
new file mode 100644
index 0000000..3085032
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_constant extends UnitTest {
+    private Resources mRes;
+
+    protected UT_constant(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Const", ctx);
+        mRes = res;
+    }
+
+    private void Assert(boolean b) {
+        if (!b) {
+            failTest();
+        }
+    }
+
+    public void run() {
+        Assert(ScriptC_constant.const_floatTest == 1.99f);
+        Assert(ScriptC_constant.const_doubleTest == 2.05);
+        Assert(ScriptC_constant.const_charTest == -8);
+        Assert(ScriptC_constant.const_shortTest == -16);
+        Assert(ScriptC_constant.const_intTest == -32);
+        Assert(ScriptC_constant.const_longTest == 17179869184l);
+        Assert(ScriptC_constant.const_longlongTest == 68719476736l);
+
+        Assert(ScriptC_constant.const_ucharTest == 8);
+        Assert(ScriptC_constant.const_ushortTest == 16);
+        Assert(ScriptC_constant.const_uintTest == 32);
+        Assert(ScriptC_constant.const_ulongTest == 4611686018427387904L);
+        Assert(ScriptC_constant.const_int64_tTest == -17179869184l);
+        Assert(ScriptC_constant.const_uint64_tTest == 117179869184l);
+
+        Assert(ScriptC_constant.const_boolTest == true);
+
+        passTest();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java
new file mode 100644
index 0000000..a7cb226
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_convert extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert s = new ScriptC_convert(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java
new file mode 100644
index 0000000..269bcef
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_convert_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert_relaxed s =
+                new ScriptC_convert_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java
new file mode 100644
index 0000000..f435dde
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java
@@ -0,0 +1,120 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_copy_test extends UnitTest {
+    private Resources mRes;
+    boolean pass = true;
+
+    protected UT_copy_test(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Copy", ctx);
+        mRes = res;
+    }
+
+    void testFloat2(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+
+        float[] f1 = new float[1024 * 2];
+        float[] f2 = new float[1024 * 2];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat2(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat3(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat3(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if ((f1[ct] != f2[ct]) && ((ct&3) != 3)) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat4(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat4(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_copy_test s = new ScriptC_copy_test(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        testFloat2(pRS, s);
+        testFloat3(pRS, s);
+        testFloat4(pRS, s);
+        s.invoke_sendResult(true);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java
new file mode 100644
index 0000000..abfa44c
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java
@@ -0,0 +1,121 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_element extends UnitTest {
+    private Resources mRes;
+
+    Element simpleElem;
+    Element complexElem;
+
+    final String subElemNames[] = {
+        "subElem0",
+        "subElem1",
+        "subElem2",
+        "arrayElem0",
+        "arrayElem1",
+        "subElem3",
+        "subElem4",
+        "subElem5",
+        "subElem6",
+        "subElem_7",
+    };
+
+    final int subElemArraySizes[] = {
+        1,
+        1,
+        1,
+        2,
+        5,
+        1,
+        1,
+        1,
+        1,
+        1,
+    };
+
+    final int subElemOffsets[] = {
+        0,
+        4,
+        8,
+        12,
+        20,
+        40,
+        44,
+        48,
+        64,
+        80,
+    };
+
+    protected UT_element(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Element", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_element s) {
+        simpleElem = Element.F32_3(RS);
+        complexElem = ScriptField_ComplexStruct.createElement(RS);
+        s.set_simpleElem(simpleElem);
+        s.set_complexElem(complexElem);
+
+        ScriptField_ComplexStruct data = new ScriptField_ComplexStruct(RS, 1);
+        s.bind_complexStruct(data);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_element s = new ScriptC_element(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_element_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+
+        int subElemCount = simpleElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 0", subElemCount == 0);
+
+        subElemCount = complexElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 10", subElemCount == 10);
+        _RS_ASSERT("complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof",
+                   complexElem.getBytesSize() == ScriptField_ComplexStruct.Item.sizeof);
+
+        for (int i = 0; i < subElemCount; i ++) {
+            _RS_ASSERT("complexElem.getSubElement(i) != null",
+                       complexElem.getSubElement(i) != null);
+            _RS_ASSERT("complexElem.getSubElementName(i).equals(subElemNames[i])",
+                       complexElem.getSubElementName(i).equals(subElemNames[i]));
+            _RS_ASSERT("complexElem.getSubElementArraySize(i) == subElemArraySizes[i]",
+                       complexElem.getSubElementArraySize(i) == subElemArraySizes[i]);
+            _RS_ASSERT("complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]",
+                       complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]);
+        }
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
new file mode 100644
index 0000000..fd18f93
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011-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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_foreach extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach s = new ScriptC_foreach(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(A);
+        s.invoke_verify_root();
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_foreach_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
new file mode 100644
index 0000000..13fefe7
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_foreach_bounds extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach_bounds(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (bounds)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach_bounds s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+        s.set_s(s);
+        s.set_ain(A);
+        s.set_aout(A);
+        s.set_xStart(2);
+        s.set_xEnd(5);
+        s.set_yStart(3);
+        s.set_yEnd(6);
+        s.forEach_zero(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach_bounds s = new ScriptC_foreach_bounds(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_foreach_bounds_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..960df24
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+    private Resources mRes;
+
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_fp_mad_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java
new file mode 100644
index 0000000..9592798
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_int4 extends UnitTest {
+    private Resources mRes;
+
+    protected UT_int4(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "int4", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_int4 s = new ScriptC_int4(pRS, mRes, R.raw.int4);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_int4_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java
new file mode 100644
index 0000000..ec67665
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        s.set_dimX(X);
+        typeBuilder.setX(X);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_ain(A);
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_aout(B);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel s = new ScriptC_kernel(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java
new file mode 100644
index 0000000..07538ec
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel_struct extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (struct pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel_struct s) {
+        int X = 5;
+        s.set_dimX(X);
+        ScriptField_simpleStruct t;
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_ain(t);
+        A = t.getAllocation();
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_aout(t);
+        B = t.getAllocation();
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel_struct s = new ScriptC_kernel_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_struct_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java
new file mode 100644
index 0000000..055c454
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_math extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math s = new ScriptC_math(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..a7e7429
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,527 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Random;
+
+public class UT_math_agree extends UnitTest {
+    private Resources mRes;
+    private Random rand;
+
+    protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Agreement", ctx);
+        mRes = res;
+        rand = new Random();
+    }
+
+    // packing functions
+    private Float2 pack_f2(float[] val) {
+        assert val.length == 2;
+        return new Float2(val[0], val[1]);
+    }
+    private Float3 pack_f3(float[] val) {
+        assert val.length == 3;
+        return new Float3(val[0], val[1], val[2]);
+    }
+    private Float4 pack_f4(float[] val) {
+        assert val.length == 4;
+        return new Float4(val[0], val[1], val[2], val[3]);
+    }
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        return new Byte2(val[0], val[1]);
+    }
+    private Byte3 pack_b3(byte[] val) {
+        assert val.length == 3;
+        return new Byte3(val[0], val[1], val[2]);
+    }
+    private Byte4 pack_b4(byte[] val) {
+        assert val.length == 4;
+        return new Byte4(val[0], val[1], val[2], val[3]);
+    }
+    private Short2 pack_s2(short[] val) {
+        assert val.length == 2;
+        return new Short2(val[0], val[1]);
+    }
+    private Short3 pack_s3(short[] val) {
+        assert val.length == 3;
+        return new Short3(val[0], val[1], val[2]);
+    }
+    private Short4 pack_s4(short[] val) {
+        assert val.length == 4;
+        return new Short4(val[0], val[1], val[2], val[3]);
+    }
+    private Int2 pack_i2(int[] val) {
+        assert val.length == 2;
+        return new Int2(val[0], val[1]);
+    }
+    private Int3 pack_i3(int[] val) {
+        assert val.length == 3;
+        return new Int3(val[0], val[1], val[2]);
+    }
+    private Int4 pack_i4(int[] val) {
+        assert val.length == 4;
+        return new Int4(val[0], val[1], val[2], val[3]);
+    }
+    private Long2 pack_l2(long[] val) {
+        assert val.length == 2;
+        return new Long2(val[0], val[1]);
+    }
+    private Long3 pack_l3(long[] val) {
+        assert val.length == 3;
+        return new Long3(val[0], val[1], val[2]);
+    }
+    private Long4 pack_l4(long[] val) {
+        assert val.length == 4;
+        return new Long4(val[0], val[1], val[2], val[3]);
+    }
+
+    // random vector generation functions
+    private float[] randvec_float(int dim) {
+        float[] fv = new float[dim];
+        for (int i = 0; i < dim; ++i)
+            fv[i] = rand.nextFloat();
+        return fv;
+    }
+    private byte[] randvec_char(int dim) {
+        byte[] cv = new byte[dim];
+        rand.nextBytes(cv);
+        return cv;
+    }
+    private short[] randvec_uchar(int dim) {
+       short[] ucv = new short[dim];
+       for (int i = 0; i < dim; ++i)
+           ucv[i] = (short)rand.nextInt(0x1 << 8);
+       return ucv;
+    }
+    private short[] randvec_short(int dim) {
+        short[] sv = new short[dim];
+        for (int i = 0; i < dim; ++i)
+            sv[i] = (short)rand.nextInt(0x1 << 16);
+        return sv;
+    }
+    private int[] randvec_ushort(int dim) {
+        int[] usv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            usv[i] = rand.nextInt(0x1 << 16);
+        return usv;
+    }
+    private int[] randvec_int(int dim) {
+        int[] iv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            iv[i] = rand.nextInt();
+        return iv;
+    }
+    private long[] randvec_uint(int dim) {
+        long[] uiv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        return uiv;
+    }
+    private long[] randvec_long(int dim) {
+        long[] lv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            lv[i] = rand.nextLong();
+        return lv;
+    }
+    // TODO:  unsigned long generator
+
+    // min reference functions
+    private float min(float v1, float v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private float[] min(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private short min(short v1, short v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private short[] min(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private int min(int v1, int v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private int[] min(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private long min(long v1, long v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private long[] min(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of min
+
+    // max reference functions
+    private float max(float v1, float v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private float[] max(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private byte max(byte v1, byte v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private byte[] max(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private short max(short v1, short v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private short[] max(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private int max(int v1, int v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private int[] max(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private long max(long v1, long v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private long[] max(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of max
+
+    // fmin reference functions
+    private float fmin(float v1, float v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float[] v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2);
+        return rv;
+    }
+
+    // fmax reference functions
+    private float fmax(float v1, float v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float[] v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_math_agree s) {
+        float x = rand.nextFloat();
+        float y = rand.nextFloat();
+
+        s.set_x(x);
+        s.set_y(y);
+        s.set_result_add(x + y);
+        s.set_result_sub(x - y);
+        s.set_result_mul(x * y);
+        s.set_result_div(x / y);
+
+        // Generate random vectors of all types
+        float rand_f1_0 = rand.nextFloat();
+        float[] rand_f2_0 = randvec_float(2);
+        float[] rand_f3_0 = randvec_float(3);
+        float[] rand_f4_0 = randvec_float(4);
+        float rand_f1_1 = rand.nextFloat();
+        float[] rand_f2_1 = randvec_float(2);
+        float[] rand_f3_1 = randvec_float(3);
+        float[] rand_f4_1 = randvec_float(4);
+        short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_0 = randvec_uchar(2);
+        short[] rand_uc3_0 = randvec_uchar(3);
+        short[] rand_uc4_0 = randvec_uchar(4);
+        short rand_uc1_1 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_1 = randvec_uchar(2);
+        short[] rand_uc3_1 = randvec_uchar(3);
+        short[] rand_uc4_1 = randvec_uchar(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
+        int rand_us1_0 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_0 = randvec_ushort(2);
+        int[] rand_us3_0 = randvec_ushort(3);
+        int[] rand_us4_0 = randvec_ushort(4);
+        int rand_us1_1 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_1 = randvec_ushort(2);
+        int[] rand_us3_1 = randvec_ushort(3);
+        int[] rand_us4_1 = randvec_ushort(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
+        long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_0 = randvec_uint(2);
+        long[] rand_ui3_0 = randvec_uint(3);
+        long[] rand_ui4_0 = randvec_uint(4);
+        long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_1 = randvec_uint(2);
+        long[] rand_ui3_1 = randvec_uint(3);
+        long[] rand_ui4_1 = randvec_uint(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
+        // TODO:  generate unsigned long vectors
+
+        // Set random vectors in renderscript code
+        s.set_rand_f1_0(rand_f1_0);
+        s.set_rand_f2_0(pack_f2(rand_f2_0));
+        s.set_rand_f3_0(pack_f3(rand_f3_0));
+        s.set_rand_f4_0(pack_f4(rand_f4_0));
+        s.set_rand_f1_1(rand_f1_1);
+        s.set_rand_f2_1(pack_f2(rand_f2_1));
+        s.set_rand_f3_1(pack_f3(rand_f3_1));
+        s.set_rand_f4_1(pack_f4(rand_f4_1));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_ss1_0(rand_ss1_0);
+        s.set_rand_ss2_0(pack_s2(rand_ss2_0));
+        s.set_rand_ss3_0(pack_s3(rand_ss3_0));
+        s.set_rand_ss4_0(pack_s4(rand_ss4_0));
+        s.set_rand_ss1_1(rand_ss1_1);
+        s.set_rand_ss2_1(pack_s2(rand_ss2_1));
+        s.set_rand_ss3_1(pack_s3(rand_ss3_1));
+        s.set_rand_ss4_1(pack_s4(rand_ss4_1));
+        s.set_rand_us1_0(rand_us1_0);
+        s.set_rand_us2_0(pack_i2(rand_us2_0));
+        s.set_rand_us3_0(pack_i3(rand_us3_0));
+        s.set_rand_us4_0(pack_i4(rand_us4_0));
+        s.set_rand_us1_1(rand_us1_1);
+        s.set_rand_us2_1(pack_i2(rand_us2_1));
+        s.set_rand_us3_1(pack_i3(rand_us3_1));
+        s.set_rand_us4_1(pack_i4(rand_us4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
+        s.set_rand_ui1_0(rand_ui1_0);
+        s.set_rand_ui2_0(pack_l2(rand_ui2_0));
+        s.set_rand_ui3_0(pack_l3(rand_ui3_0));
+        s.set_rand_ui4_0(pack_l4(rand_ui4_0));
+        s.set_rand_ui1_1(rand_ui1_1);
+        s.set_rand_ui2_1(pack_l2(rand_ui2_1));
+        s.set_rand_ui3_1(pack_l3(rand_ui3_1));
+        s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        // TODO:  set unsigned long vectors
+
+        // Set results for min
+        s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1));
+        s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
+        s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
+        s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s2(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
+        s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
+        s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
+        s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
+        s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
+        s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
+        s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
+        s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
+        s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
+        s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
+        s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
+        s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
+        s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
+        s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
+        s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
+        // TODO:  set results for unsigned long min
+
+        // Set results for max
+        s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1));
+        s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
+        s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
+        s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s2(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
+        s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
+        s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
+        s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
+        s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
+        s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
+        s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
+        s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
+        s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
+        s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
+        s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
+        s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
+        s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
+        s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
+        s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
+        s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
+        s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
+
+        // TODO:  set results for unsigned long max
+
+        // Set results for fmin
+        s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1));
+        s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1)));
+        s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1)));
+        s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1)));
+        s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1)));
+        s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1)));
+        s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1)));
+
+        // Set results for fmax
+        s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1));
+        s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1)));
+        s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1)));
+        s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1)));
+        s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1)));
+        s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1)));
+        s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1)));
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_agree s = new ScriptC_math_agree(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_math_agree_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java
new file mode 100644
index 0000000..384cd13
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_math_conformance extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math_conformance(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Conformance", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_conformance s =
+                new ScriptC_math_conformance(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_conformance_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java
new file mode 100644
index 0000000..cea9fe5
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_min extends UnitTest {
+    private Resources mRes;
+
+    protected UT_min(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Min (relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_min s = new ScriptC_min(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_min_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
new file mode 100644
index 0000000..606af4d
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011-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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_noroot extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_noroot(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (no root)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_noroot s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_noroot s = new ScriptC_noroot(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_noroot_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..3c663a8
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,103 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+    private Resources mRes;
+
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_primitives s) {
+        float pF = s.get_floatTest();
+        if (pF != 1.99f) {
+            return false;
+        }
+        s.set_floatTest(2.99f);
+
+        double pD = s.get_doubleTest();
+        if (pD != 2.05) {
+            return false;
+        }
+        s.set_doubleTest(3.05);
+
+        byte pC = s.get_charTest();
+        if (pC != -8) {
+            return false;
+        }
+        s.set_charTest((byte)-16);
+
+        short pS = s.get_shortTest();
+        if (pS != -16) {
+            return false;
+        }
+        s.set_shortTest((short)-32);
+
+        int pI = s.get_intTest();
+        if (pI != -32) {
+            return false;
+        }
+        s.set_intTest(-64);
+
+        long pL = s.get_longTest();
+        if (pL != 17179869184l) {
+            return false;
+        }
+        s.set_longTest(17179869185l);
+
+        long puL = s.get_ulongTest();
+        if (puL != 4611686018427387904L) {
+            return false;
+        }
+        s.set_ulongTest(4611686018427387903L);
+
+
+        long pLL = s.get_longlongTest();
+        if (pLL != 68719476736L) {
+            return false;
+        }
+        s.set_longlongTest(68719476735L);
+
+        long pu64 = s.get_uint64_tTest();
+        if (pu64 != 117179869184l) {
+            return false;
+        }
+        s.set_uint64_tTest(117179869185l);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_primitives s = new ScriptC_primitives(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_primitives_test(0, 0);
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java
new file mode 100644
index 0000000..e6317d5
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_refcount extends UnitTest {
+    private Resources mRes;
+
+    protected UT_refcount(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Refcount", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_refcount s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 500;
+        int Y = 700;
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_globalA(A);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        pRS.setMessageHandler(mRsMessage);
+        ScriptC_refcount s = new ScriptC_refcount(pRS);
+        initializeGlobals(pRS, s);
+        s.invoke_refcount_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java
new file mode 100644
index 0000000..740180e
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rsdebug extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rsdebug(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..86e35a8
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.setTimeZone("America/Los_Angeles");
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java
new file mode 100644
index 0000000..3245eca
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rstypes extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstypes(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java
new file mode 100644
index 0000000..d8d5a78
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java
@@ -0,0 +1,148 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_sampler extends UnitTest {
+    private Resources mRes;
+
+    Sampler minification;
+    Sampler magnification;
+    Sampler wrapS;
+    Sampler wrapT;
+    Sampler anisotropy;
+
+    protected UT_sampler(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Sampler", ctx);
+        mRes = res;
+    }
+
+    private Sampler.Builder getDefaultBuilder(RenderScript RS) {
+        Sampler.Builder b = new Sampler.Builder(RS);
+        b.setMinification(Sampler.Value.NEAREST);
+        b.setMagnification(Sampler.Value.NEAREST);
+        b.setWrapS(Sampler.Value.CLAMP);
+        b.setWrapT(Sampler.Value.CLAMP);
+        b.setAnisotropy(1.0f);
+        return b;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_sampler s) {
+        Sampler.Builder b = getDefaultBuilder(RS);
+        b.setMinification(Sampler.Value.LINEAR_MIP_LINEAR);
+        minification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setMagnification(Sampler.Value.LINEAR);
+        magnification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapS(Sampler.Value.WRAP);
+        wrapS = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapT(Sampler.Value.WRAP);
+        wrapT = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setAnisotropy(8.0f);
+        anisotropy = b.create();
+
+        s.set_minification(minification);
+        s.set_magnification(magnification);
+        s.set_wrapS(wrapS);
+        s.set_wrapT(wrapT);
+        s.set_anisotropy(anisotropy);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_sampler s = new ScriptC_sampler(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_sampler_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+        _RS_ASSERT("minification.getMagnification() == Sampler.Value.NEAREST",
+                    minification.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR",
+                    minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR);
+        _RS_ASSERT("minification.getWrapS() == Sampler.Value.CLAMP",
+                    minification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getWrapT() == Sampler.Value.CLAMP",
+                    minification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getAnisotropy() == 1.0f",
+                    minification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("magnification.getMagnification() == Sampler.Value.LINEAR",
+                    magnification.getMagnification() == Sampler.Value.LINEAR);
+        _RS_ASSERT("magnification.getMinification() == Sampler.Value.NEAREST",
+                    magnification.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("magnification.getWrapS() == Sampler.Value.CLAMP",
+                    magnification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getWrapT() == Sampler.Value.CLAMP",
+                    magnification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getAnisotropy() == 1.0f",
+                    magnification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapS.getMagnification() == Sampler.Value.NEAREST",
+                    wrapS.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getMinification() == Sampler.Value.NEAREST",
+                    wrapS.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getWrapS() == Sampler.Value.WRAP",
+                    wrapS.getWrapS() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapS.getWrapT() == Sampler.Value.CLAMP",
+                    wrapS.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapS.getAnisotropy() == 1.0f",
+                    wrapS.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapT.getMagnification() == Sampler.Value.NEAREST",
+                    wrapT.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getMinification() == Sampler.Value.NEAREST",
+                    wrapT.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getWrapS() == Sampler.Value.CLAMP",
+                    wrapT.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapT.getWrapT() == Sampler.Value.WRAP",
+                    wrapT.getWrapT() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapT.getAnisotropy() == 1.0f",
+                    wrapT.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("anisotropy.getMagnification() == Sampler.Value.NEAREST",
+                    anisotropy.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getMinification() == Sampler.Value.NEAREST",
+                    anisotropy.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getWrapS() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getWrapT() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getAnisotropy() == 1.0f",
+                    anisotropy.getAnisotropy() == 8.0f);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java
new file mode 100644
index 0000000..43bbaf7
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_struct extends UnitTest {
+    private Resources mRes;
+
+    protected UT_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Struct", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_struct s = new ScriptC_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        ScriptField_Point2 p = new ScriptField_Point2(pRS, 1);
+        ScriptField_Point2.Item i = new ScriptField_Point2.Item();
+        int val = 100;
+        i.x = val;
+        i.y = val;
+        p.set(i, 0, true);
+        s.bind_point2(p);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+
+        val = 200;
+        p.set_x(0, val, true);
+        p.set_y(0, val, true);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java
new file mode 100644
index 0000000..0e16240
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_unsigned extends UnitTest {
+    private Resources mRes;
+
+    protected UT_unsigned(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Unsigned", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_unsigned s) {
+        short pUC = s.get_uc();
+        if (pUC != 5) {
+            return false;
+        }
+        s.set_uc((short)129);
+
+        long pUI = s.get_ui();
+        if (pUI != 37) {
+            return false;
+        }
+        s.set_ui(0x7fffffff);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_unsigned s = new ScriptC_unsigned(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_unsigned_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java
new file mode 100644
index 0000000..6ba822e
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java
@@ -0,0 +1,318 @@
+/*
+ * 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 com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_vector extends UnitTest {
+    private Resources mRes;
+
+    protected UT_vector(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Vector", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_vector s) {
+        Float2 F2 = s.get_f2();
+        if (F2.x != 1.0f || F2.y != 2.0f) {
+            return false;
+        }
+        F2.x = 2.99f;
+        F2.y = 3.99f;
+        s.set_f2(F2);
+
+        Float3 F3 = s.get_f3();
+        if (F3.x != 1.0f || F3.y != 2.0f || F3.z != 3.0f) {
+            return false;
+        }
+        F3.x = 2.99f;
+        F3.y = 3.99f;
+        F3.z = 4.99f;
+        s.set_f3(F3);
+
+        Float4 F4 = s.get_f4();
+        if (F4.x != 1.0f || F4.y != 2.0f || F4.z != 3.0f || F4.w != 4.0f) {
+            return false;
+        }
+        F4.x = 2.99f;
+        F4.y = 3.99f;
+        F4.z = 4.99f;
+        F4.w = 5.99f;
+        s.set_f4(F4);
+
+        Double2 D2 = s.get_d2();
+        if (D2.x != 1.0 || D2.y != 2.0) {
+            return false;
+        }
+        D2.x = 2.99;
+        D2.y = 3.99;
+        s.set_d2(D2);
+
+        Double3 D3 = s.get_d3();
+        if (D3.x != 1.0 || D3.y != 2.0 || D3.z != 3.0) {
+            return false;
+        }
+        D3.x = 2.99;
+        D3.y = 3.99;
+        D3.z = 4.99;
+        s.set_d3(D3);
+
+        Double4 D4 = s.get_d4();
+        if (D4.x != 1.0 || D4.y != 2.0 || D4.z != 3.0 || D4.w != 4.0) {
+            return false;
+        }
+        D4.x = 2.99;
+        D4.y = 3.99;
+        D4.z = 4.99;
+        D4.w = 5.99;
+        s.set_d4(D4);
+
+        Byte2 B2 = s.get_i8_2();
+        if (B2.x != 1 || B2.y != 2) {
+            return false;
+        }
+        B2.x = 2;
+        B2.y = 3;
+        s.set_i8_2(B2);
+
+        Byte3 B3 = s.get_i8_3();
+        if (B3.x != 1 || B3.y != 2 || B3.z != 3) {
+            return false;
+        }
+        B3.x = 2;
+        B3.y = 3;
+        B3.z = 4;
+        s.set_i8_3(B3);
+
+        Byte4 B4 = s.get_i8_4();
+        if (B4.x != 1 || B4.y != 2 || B4.z != 3 || B4.w != 4) {
+            return false;
+        }
+        B4.x = 2;
+        B4.y = 3;
+        B4.z = 4;
+        B4.w = 5;
+        s.set_i8_4(B4);
+
+        Short2 S2 = s.get_u8_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_u8_2(S2);
+
+        Short3 S3 = s.get_u8_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_u8_3(S3);
+
+        Short4 S4 = s.get_u8_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_u8_4(S4);
+
+        S2 = s.get_i16_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_i16_2(S2);
+
+        S3 = s.get_i16_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_i16_3(S3);
+
+        S4 = s.get_i16_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_i16_4(S4);
+
+        Int2 I2 = s.get_u16_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_u16_2(I2);
+
+        Int3 I3 = s.get_u16_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_u16_3(I3);
+
+        Int4 I4 = s.get_u16_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_u16_4(I4);
+
+        I2 = s.get_i32_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_i32_2(I2);
+
+        I3 = s.get_i32_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_i32_3(I3);
+
+        I4 = s.get_i32_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_i32_4(I4);
+
+        Long2 L2 = s.get_u32_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u32_2(L2);
+
+        Long3 L3 = s.get_u32_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u32_3(L3);
+
+        Long4 L4 = s.get_u32_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u32_4(L4);
+
+        L2 = s.get_i64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_i64_2(L2);
+
+        L3 = s.get_i64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_i64_3(L3);
+
+        L4 = s.get_i64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_i64_4(L4);
+
+        L2 = s.get_u64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u64_2(L2);
+
+        L3 = s.get_u64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u64_3(L3);
+
+        L4 = s.get_u64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u64_4(L4);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_vector s = new ScriptC_vector(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_vector_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..01abf2f
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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 com.android.rs.test_compat;
+import android.content.Context;
+import android.util.Log;
+import android.support.v8.renderscript.RenderScript.RSMessageHandler;
+
+public class UnitTest extends Thread {
+    public String name;
+    private int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
+    }
+
+    protected void _RS_ASSERT(String message, boolean b) {
+        if(b == false) {
+            Log.e(name, message + " FAILED");
+            failTest();
+        }
+    }
+
+    private void updateUI() {
+        if (mItem != null) {
+            mItem.result = result;
+            msgHandled = true;
+            try {
+                mRSTC.refreshTestResults();
+            }
+            catch (IllegalStateException e) {
+                /* Ignore the case where our message receiver has been
+                   disconnected. This happens when we leave the application
+                   before it finishes running all of the unit tests. */
+            }
+        }
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = 1;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = -1;
+                        break;
+                    default:
+                        RSTest.log("Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            updateUI();
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public int getResult() {
+        return result;
+    }
+
+    public void failTest() {
+        result = -1;
+        updateUI();
+    }
+
+    public void passTest() {
+        if (result != -1) {
+            result = 1;
+        }
+        updateUI();
+    }
+
+    public String toString() {
+        String out = name;
+        if (result == 1) {
+            out += " - PASSED";
+        }
+        else if (result == -1) {
+            out += " - FAILED";
+        }
+        return out;
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
new file mode 100644
index 0000000..1b5e2ac
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
@@ -0,0 +1,92 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int dimZ;
+
+rs_allocation aRaw;
+rs_allocation aFaces;
+rs_allocation aLOD;
+rs_allocation aFacesLOD;
+
+void root(int *o, uint32_t x, uint32_t y) {
+    *o = x + y * dimX;
+}
+
+static bool test_alloc_dims() {
+    bool failed = false;
+    int i, j;
+
+    _RS_ASSERT(rsAllocationGetDimX(aRaw) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aRaw) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aRaw) == dimZ);
+
+    // Test 2D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(aRaw, i, j);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    // Test 1D addressing
+    for (i = 0; i < dimX; i++) {
+        rsDebug("Verifying ", i);
+        const void *p = rsGetElementAt(aRaw, i);
+        int val = *(const int *)p;
+        _RS_ASSERT(val == i);
+    }
+
+    // Test 3D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(aRaw, i, j, 0);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    _RS_ASSERT(rsAllocationGetDimX(aFaces) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFaces) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFaces) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFaces) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFaces) == 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aLOD) == 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aLOD) != 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aFacesLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFacesLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFacesLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFacesLOD) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFacesLOD) != 0);
+
+    if (failed) {
+        rsDebug("test_alloc_dims FAILED", 0);
+    }
+    else {
+        rsDebug("test_alloc_dims PASSED", 0);
+    }
+
+    return failed;
+}
+
+void alloc_test() {
+    bool failed = false;
+    failed |= test_alloc_dims();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs
new file mode 100644
index 0000000..74ffdb1
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs
@@ -0,0 +1,21 @@
+#include "shared.rsh"
+
+const int dimX = 20;
+rs_allocation a[dimX];
+
+void array_alloc_test() {
+    bool failed = false;
+
+    for (int i = 0; i < dimX; i++) {
+        rsDebug("i: ", i);
+        _RS_ASSERT(rsAllocationGetDimX(a[i]) == 1);
+    }
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs
new file mode 100644
index 0000000..842249a
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs
@@ -0,0 +1,58 @@
+#include "shared.rsh"
+
+// Testing constant array initialization
+float fa[4] = {1.0, 9.9999f};
+double da[2] = {7.0, 8.88888};
+char ca[4] = {'a', 7, 'b', 'c'};
+short sa[4] = {1, 1, 2, 3};
+int ia[4] = {5, 8};
+long la[2] = {13, 21};
+long long lla[4] = {34};
+bool ba[3] = {true, false};
+
+void array_init_test() {
+    bool failed = false;
+
+    _RS_ASSERT(fa[0] == 1.0);
+    _RS_ASSERT(fa[1] == 9.9999f);
+    _RS_ASSERT(fa[2] == 0);
+    _RS_ASSERT(fa[3] == 0);
+
+    _RS_ASSERT(da[0] == 7.0);
+    _RS_ASSERT(da[1] == 8.88888);
+
+    _RS_ASSERT(ca[0] == 'a');
+    _RS_ASSERT(ca[1] == 7);
+    _RS_ASSERT(ca[2] == 'b');
+    _RS_ASSERT(ca[3] == 'c');
+
+    _RS_ASSERT(sa[0] == 1);
+    _RS_ASSERT(sa[1] == 1);
+    _RS_ASSERT(sa[2] == 2);
+    _RS_ASSERT(sa[3] == 3);
+
+    _RS_ASSERT(ia[0] == 5);
+    _RS_ASSERT(ia[1] == 8);
+    _RS_ASSERT(ia[2] == 0);
+    _RS_ASSERT(ia[3] == 0);
+
+    _RS_ASSERT(la[0] == 13);
+    _RS_ASSERT(la[1] == 21);
+
+    _RS_ASSERT(lla[0] == 34);
+    _RS_ASSERT(lla[1] == 0);
+    _RS_ASSERT(lla[2] == 0);
+    _RS_ASSERT(lla[3] == 0);
+
+    _RS_ASSERT(ba[0] == true);
+    _RS_ASSERT(ba[1] == false);
+    _RS_ASSERT(ba[2] == false);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs
new file mode 100644
index 0000000..f0a5041
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs
@@ -0,0 +1,77 @@
+#include "shared.rsh"
+
+// Testing atomic operations
+static bool testUMax(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst > src ? dst : src);
+    uint32_t ret = rsAtomicMax(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUMin(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst < src ? dst : src);
+    uint32_t ret = rsAtomicMin(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUCas(uint32_t dst, uint32_t cmp, uint32_t swp) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst == cmp ? swp : dst);
+    uint32_t ret = rsAtomicCas(&dst, cmp, swp);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool test_atomics() {
+    bool failed = false;
+
+    failed |= testUMax(5, 6);
+    failed |= testUMax(6, 5);
+    failed |= testUMax(5, 0xf0000006);
+    failed |= testUMax(0xf0000006, 5);
+
+    failed |= testUMin(5, 6);
+    failed |= testUMin(6, 5);
+    failed |= testUMin(5, 0xf0000006);
+    failed |= testUMin(0xf0000006, 5);
+
+    failed |= testUCas(4, 4, 5);
+    failed |= testUCas(4, 5, 5);
+    failed |= testUCas(5, 5, 4);
+    failed |= testUCas(5, 4, 4);
+    failed |= testUCas(0xf0000004, 0xf0000004, 0xf0000005);
+    failed |= testUCas(0xf0000004, 0xf0000005, 0xf0000005);
+    failed |= testUCas(0xf0000005, 0xf0000005, 0xf0000004);
+    failed |= testUCas(0xf0000005, 0xf0000004, 0xf0000004);
+
+    if (failed) {
+        rsDebug("test_atomics FAILED", 0);
+    }
+    else {
+        rsDebug("test_atomics PASSED", 0);
+    }
+
+    return failed;
+}
+
+void atomic_test() {
+    bool failed = false;
+    failed |= test_atomics();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs
new file mode 100644
index 0000000..dcd7b72
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+char rand_sc1_0, rand_sc1_1;
+char2 rand_sc2_0, rand_sc2_1;
+
+char min_rand_sc1_sc1;
+char2 min_rand_sc2_sc2;
+
+static bool test_bug_char() {
+    bool failed = false;
+
+    rsDebug("rand_sc2_0.x: ", rand_sc2_0.x);
+    rsDebug("rand_sc2_0.y: ", rand_sc2_0.y);
+    rsDebug("rand_sc2_1.x: ", rand_sc2_1.x);
+    rsDebug("rand_sc2_1.y: ", rand_sc2_1.y);
+    char temp_sc1;
+    char2 temp_sc2;
+
+    temp_sc1 = min( rand_sc1_0, rand_sc1_1 );
+    if (temp_sc1 != min_rand_sc1_sc1) {
+        rsDebug("temp_sc1", temp_sc1);
+        failed = true;
+    }
+    rsDebug("broken", 'y');
+
+    temp_sc2 = min( rand_sc2_0, rand_sc2_1 );
+    if (temp_sc2.x != min_rand_sc2_sc2.x
+            || temp_sc2.y != min_rand_sc2_sc2.y) {
+        failed = true;
+    }
+
+
+    return failed;
+}
+
+void bug_char_test() {
+    bool failed = false;
+    failed |= test_bug_char();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs
new file mode 100644
index 0000000..28b00bd
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs
@@ -0,0 +1,56 @@
+#include "shared.rsh"
+
+static bool test_clamp_vector() {
+    bool failed = false;
+
+    float2 src2 = { 2.0f, 2.0f};
+    float2 min2 = { 0.5f, -3.0f};
+    float2 max2 = { 1.0f, 9.0f};
+
+    float2 res2 = clamp(src2, min2, max2);
+    _RS_ASSERT(res2.x == 1.0f);
+    _RS_ASSERT(res2.y == 2.0f);
+
+
+    float3 src3 = { 2.0f, 2.0f, 1.0f};
+    float3 min3 = { 0.5f, -3.0f, 3.0f};
+    float3 max3 = { 1.0f, 9.0f, 4.0f};
+
+    float3 res3 = clamp(src3, min3, max3);
+    _RS_ASSERT(res3.x == 1.0f);
+    _RS_ASSERT(res3.y == 2.0f);
+    _RS_ASSERT(res3.z == 3.0f);
+
+
+    float4 src4 = { 2.0f, 2.0f, 1.0f, 4.0f };
+    float4 min4 = { 0.5f, -3.0f, 3.0f, 4.0f };
+    float4 max4 = { 1.0f, 9.0f, 4.0f, 4.0f };
+
+    float4 res4 = clamp(src4, min4, max4);
+    _RS_ASSERT(res4.x == 1.0f);
+    _RS_ASSERT(res4.y == 2.0f);
+    _RS_ASSERT(res4.z == 3.0f);
+    _RS_ASSERT(res4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_clamp_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_clamp_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void clamp_test() {
+    bool failed = false;
+    failed |= test_clamp_vector();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs
new file mode 100644
index 0000000..71c65ae
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs
@@ -0,0 +1,2 @@
+#include "clamp.rs"
+#pragma rs_fp_relaxed
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/constant.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/constant.rs
new file mode 100644
index 0000000..732eaef
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/constant.rs
@@ -0,0 +1,19 @@
+#include "shared.rsh"
+
+const float floatTest = 1.99f;
+const double doubleTest = 2.05;
+const char charTest = -8;
+const short shortTest = -16;
+const int intTest = -32;
+const long longTest = 17179869184l; // 1 << 34
+const long long longlongTest = 68719476736l; // 1 << 36
+
+const uchar ucharTest = 8;
+const ushort ushortTest = 16;
+const uint uintTest = 32;
+const ulong ulongTest = 4611686018427387904L;
+const int64_t int64_tTest = -17179869184l; // - 1 << 34
+const uint64_t uint64_tTest = 117179869184l;
+
+const bool boolTest = true;
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/convert.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/convert.rs
new file mode 100644
index 0000000..e314f2b
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/convert.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+float4 f4 = { 2.0f, 4.0f, 6.0f, 8.0f };
+
+char4 i8_4 = { -1, -2, -3, 4 };
+
+static bool test_convert() {
+    bool failed = false;
+
+    f4 = convert_float4(i8_4);
+    _RS_ASSERT(f4.x == -1.0f);
+    _RS_ASSERT(f4.y == -2.0f);
+    _RS_ASSERT(f4.z == -3.0f);
+    _RS_ASSERT(f4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void convert_test() {
+    bool failed = false;
+    failed |= test_convert();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs
new file mode 100644
index 0000000..81abb9b
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs
@@ -0,0 +1,2 @@
+#include "convert.rs"
+#pragma rs_fp_relaxed
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs
new file mode 100644
index 0000000..f4243eb
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "shared.rsh"
+
+void sendResult(bool pass) {
+    if (pass) {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+}
+
+
+float2 __attribute((kernel)) copyFloat2(float2 i) {
+    return i;
+}
+
+float3 __attribute((kernel)) copyFloat3(float3 i) {
+    return i;
+}
+
+float4 __attribute((kernel)) copyFloat4(float4 i) {
+    return i;
+}
+
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/element.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/element.rs
new file mode 100644
index 0000000..1f24775
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/element.rs
@@ -0,0 +1,156 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element simpleElem;
+rs_element complexElem;
+typedef struct ComplexStruct {
+    float subElem0;
+    float subElem1;
+    int subElem2;
+    float arrayElem0[2];
+    int arrayElem1[5];
+    char subElem3;
+    float subElem4;
+    float2 subElem5;
+    float3 subElem6;
+    float4 subElem_7;
+} ComplexStruct_t;
+
+ComplexStruct_t *complexStruct;
+
+static const char *subElemNames[] = {
+    "subElem0",
+    "subElem1",
+    "subElem2",
+    "arrayElem0",
+    "arrayElem1",
+    "subElem3",
+    "subElem4",
+    "subElem5",
+    "subElem6",
+    "subElem_7",
+};
+
+static uint32_t subElemNamesSizes[] = {
+    8,
+    8,
+    8,
+    10,
+    10,
+    8,
+    8,
+    8,
+    8,
+    9,
+};
+
+static uint32_t subElemArraySizes[] = {
+    1,
+    1,
+    1,
+    2,
+    5,
+    1,
+    1,
+    1,
+    1,
+    1,
+};
+
+static void resetStruct() {
+    uint8_t *bytePtr = (uint8_t*)complexStruct;
+    uint32_t sizeOfStruct = sizeof(*complexStruct);
+    for(uint32_t i = 0; i < sizeOfStruct; i ++) {
+        bytePtr[i] = 0;
+    }
+}
+
+static bool equals(const char *name0, const char * name1, uint32_t len) {
+    for (uint32_t i = 0; i < len; i ++) {
+        if (name0[i] != name1[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool test_element_getters() {
+    bool failed = false;
+
+    uint32_t subElemOffsets[10];
+    uint32_t index = 0;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem0   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem1   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem2   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem0 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem1 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem3   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem4   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem5   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem6   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem_7  - (uint32_t)complexStruct;
+
+    uint32_t subElemCount = rsElementGetSubElementCount(simpleElem);
+    _RS_ASSERT(subElemCount == 0);
+    _RS_ASSERT(rsElementGetDataType(simpleElem) == RS_TYPE_FLOAT_32);
+    _RS_ASSERT(rsElementGetVectorSize(simpleElem) == 3);
+
+    subElemCount = rsElementGetSubElementCount(complexElem);
+    _RS_ASSERT(subElemCount == 10);
+    _RS_ASSERT(rsElementGetDataType(complexElem) == RS_TYPE_NONE);
+    _RS_ASSERT(rsElementGetVectorSize(complexElem) == 1);
+    _RS_ASSERT(rsElementGetBytesSize(complexElem) == sizeof(*complexStruct));
+
+    char buffer[64];
+    for (uint32_t i = 0; i < subElemCount; i ++) {
+        rs_element subElem = rsElementGetSubElement(complexElem, i);
+        _RS_ASSERT(rsIsObject(subElem));
+
+        _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, i) == subElemNamesSizes[i] + 1);
+
+        uint32_t written = rsElementGetSubElementName(complexElem, i, buffer, 64);
+        _RS_ASSERT(written == subElemNamesSizes[i]);
+        _RS_ASSERT(equals(buffer, subElemNames[i], written));
+
+        _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, i) == subElemArraySizes[i]);
+        _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, i) == subElemOffsets[i]);
+    }
+
+    // Tests error checking
+    rs_element subElem = rsElementGetSubElement(complexElem, subElemCount);
+    _RS_ASSERT(!rsIsObject(subElem));
+
+    _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, subElemCount) == 0);
+
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, subElemCount, buffer, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, NULL, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, buffer, 0) == 0);
+    uint32_t written = rsElementGetSubElementName(complexElem, 0, buffer, 5);
+    _RS_ASSERT(written == 4);
+    _RS_ASSERT(buffer[4] == '\0');
+
+    _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, subElemCount) == 0);
+    _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, subElemCount) == 0);
+
+    if (failed) {
+        rsDebug("test_element_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_element_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void element_test() {
+    bool failed = false;
+    failed |= test_element_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
new file mode 100644
index 0000000..08e6bed
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
@@ -0,0 +1,76 @@
+#include "shared.rsh"
+
+rs_allocation aRaw;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    _RS_ASSERT(*in == (x + y * dimX));
+    *out = 99 + x + y * dimX;
+    _RS_ASSERT(*out == (99 + x + y * dimX));
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void foreach_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
new file mode 100644
index 0000000..89df090
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
@@ -0,0 +1,72 @@
+#include "shared.rsh"
+
+int dimX;
+int dimY;
+int xStart = 0;
+int xEnd = 0;
+int yStart = 0;
+int yEnd = 0;
+
+rs_script s;
+rs_allocation aRaw;
+rs_allocation ain;
+rs_allocation aout;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+int __attribute__((kernel)) zero() {
+    return 0;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            rsDebug("i: ", i);
+            rsDebug("j: ", j);
+            rsDebug("a[j][i]: ", v);
+            if (i < xStart || i >= xEnd || j < yStart || j >= yEnd) {
+                _RS_ASSERT(v == 0);
+            } else {
+                _RS_ASSERT(v == (i + j * dimX));
+            }
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void foreach_bounds_test() {
+    static bool failed = false;
+
+    rs_script_call_t rssc = {0};
+    rssc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    rssc.xStart = xStart;
+    rssc.xEnd = xEnd;
+    rssc.yStart = yStart;
+    rssc.yEnd = yEnd;
+
+    rsForEach(s, ain, aout, NULL, 0, &rssc);
+
+    failed |= test_root_output();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs
new file mode 100644
index 0000000..b6f2b2a
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs
@@ -0,0 +1,174 @@
+#include "shared.rsh"
+
+const int TEST_COUNT = 1;
+
+static float data_f1[1025];
+static float4 data_f4[1025];
+
+static void test_mad4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 80); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = (data_f4[i] * 0.02f +
+                          data_f4[i+1] * 0.04f +
+                          data_f4[i+2] * 0.05f +
+                          data_f4[i+3] * 0.1f +
+                          data_f4[i+4] * 0.2f +
+                          data_f4[i+5] * 0.2f +
+                          data_f4[i+6] * 0.1f +
+                          data_f4[i+7] * 0.05f +
+                          data_f4[i+8] * 0.04f +
+                          data_f4[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad4 M ops", 1000.f / time);
+}
+
+static void test_mad(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 20); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = (data_f1[i] * 0.02f +
+                          data_f1[i+1] * 0.04f +
+                          data_f1[i+2] * 0.05f +
+                          data_f1[i+3] * 0.1f +
+                          data_f1[i+4] * 0.2f +
+                          data_f1[i+5] * 0.2f +
+                          data_f1[i+6] * 0.1f +
+                          data_f1[i+7] * 0.05f +
+                          data_f1[i+8] * 0.04f +
+                          data_f1[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad M ops", 1000.f / time);
+}
+
+static void test_norm(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = normalize(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_norm M ops", 10.f / time);
+}
+
+static void test_sincos4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10 / 4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos4 M ops", 10.f / time);
+}
+
+static void test_sincos(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos M ops", 10.f / time);
+}
+
+static void test_clamp(uint32_t index) {
+    start();
+
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = clamp(data_f1[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp M ops", 100.f / time);
+
+    start();
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            if (data_f1[i] < -1.f) data_f1[i] = -1.f;
+            if (data_f1[i] > -1.f) data_f1[i] = 1.f;
+        }
+    }
+
+    time = end(index);
+    rsDebug("fp_clamp ref M ops", 100.f / time);
+}
+
+static void test_clamp4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100 /4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = clamp(data_f4[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp4 M ops", 100.f / time);
+}
+
+void fp_mad_test(uint32_t index, int test_num) {
+    int x;
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f;
+        data_f4[x].x = (x & 0xf) * 0.1f;
+        data_f4[x].y = (x & 0xf0) * 0.1f;
+        data_f4[x].z = (x & 0x33) * 0.1f;
+        data_f4[x].w = (x & 0x77) * 0.1f;
+    }
+
+    test_mad4(index);
+    test_mad(index);
+
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].x = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].y = (x & 0xf0) * 0.1f + 1.f;
+        data_f4[x].z = (x & 0x33) * 0.1f + 1.f;
+        data_f4[x].w = (x & 0x77) * 0.1f + 1.f;
+    }
+
+    test_norm(index);
+    test_sincos4(index);
+    test_sincos(index);
+    test_clamp4(index);
+    test_clamp(index);
+
+    // TODO Actually verify test result accuracy
+    rsDebug("fp_mad_test PASSED", 0);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/int4.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/int4.rs
new file mode 100644
index 0000000..c791cab
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/int4.rs
@@ -0,0 +1,29 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+uchar4 u4 = 4;
+int4 gi4 = {2, 2, 2, 2};
+
+void int4_test() {
+    bool failed = false;
+    int4 i4 = {u4.x, u4.y, u4.z, u4.w};
+    i4 *= gi4;
+
+    rsDebug("i4.x", i4.x);
+    rsDebug("i4.y", i4.y);
+    rsDebug("i4.z", i4.z);
+    rsDebug("i4.w", i4.w);
+
+    _RS_ASSERT(i4.x == 8);
+    _RS_ASSERT(i4.y == 8);
+    _RS_ASSERT(i4.z == 8);
+    _RS_ASSERT(i4.w == 8);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs
new file mode 100644
index 0000000..d6c9df3
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+int *ain;
+int *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(int *out) {
+    *out = 7;
+}
+
+
+int __attribute__((kernel)) root(int ain, uint32_t x) {
+    _RS_ASSERT(ain == 7);
+    return ain + x;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i] == (i + ain[i]));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs
new file mode 100644
index 0000000..62c30ae
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs
@@ -0,0 +1,66 @@
+#include "shared.rsh"
+
+struct simpleStruct {
+    int i1;
+    char ignored1;
+    float f1;
+    int i2;
+    char ignored2;
+    float f2;
+};
+
+struct simpleStruct *ain;
+struct simpleStruct *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(struct simpleStruct *out, uint32_t x) {
+    out->i1 = 0;
+    out->f1 = 0.f;
+    out->i2 = 1;
+    out->f2 = 1.0f;
+}
+
+struct simpleStruct __attribute__((kernel))
+        root(struct simpleStruct in, uint32_t x) {
+    struct simpleStruct s;
+    s.i1 = in.i1 + x;
+    s.f1 = in.f1 + x;
+    s.i2 = in.i2 + x;
+    s.f2 = in.f2 + x;
+    return s;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i].i1 == (i + ain[i].i1));
+        _RS_ASSERT(aout[i].f1 == (i + ain[i].f1));
+        _RS_ASSERT(aout[i].i2 == (i + ain[i].i2));
+        _RS_ASSERT(aout[i].f2 == (i + ain[i].f2));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_struct_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/math.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/math.rs
new file mode 100644
index 0000000..aae29a4
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/math.rs
@@ -0,0 +1,436 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_int_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..5bfbb2b
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,409 @@
+#include "shared.rsh"
+//#pragma rs_fp_relaxed
+
+volatile float x = 0.0f;
+volatile float y = 0.0f;
+volatile float result_add = 0.0f;
+volatile float result_sub = 0.0f;
+volatile float result_mul = 0.0f;
+volatile float result_div = 0.0f;
+
+#define DECLARE_INPUT_SET(type, abbrev)         \
+volatile type    rand_##abbrev##1_0, rand_##abbrev##1_1; \
+volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \
+volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \
+volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1;
+
+#define DECLARE_ALL_INPUT_SETS()    \
+DECLARE_INPUT_SET(float, f);        \
+DECLARE_INPUT_SET(char, sc);        \
+DECLARE_INPUT_SET(uchar, uc);       \
+DECLARE_INPUT_SET(short, ss);       \
+DECLARE_INPUT_SET(ushort, us);      \
+DECLARE_INPUT_SET(int, si);         \
+DECLARE_INPUT_SET(uint, ui);        \
+DECLARE_INPUT_SET(long, sl);        \
+DECLARE_INPUT_SET(ulong, ul);
+
+DECLARE_ALL_INPUT_SETS();
+
+#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func)   \
+volatile type    func##_rand_##abbrev##1_##abbrev##1;                \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##2;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##3;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##4;
+#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func)   \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##1;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##1;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##1;
+
+#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func)    \
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func);    \
+DECLARE_REFERENCE_SET_VEC_VEC(int, si, func);       \
+DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func);
+
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min);
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax);
+
+static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) {
+    int dist = float_dist(actual, expected);
+    rsDebug("float operation did not match!", op_name);
+    rsDebug("v1", v1);
+    rsDebug("v2", v2);
+    rsDebug("Dalvik result", expected);
+    rsDebug("Renderscript result", actual);
+    rsDebug("ULP difference", dist);
+}
+
+static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) {
+    int2 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    rsDebug("float2 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+}
+
+static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) {
+    int3 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    rsDebug("float3 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+}
+
+static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) {
+    int4 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    dist.w = float_dist(actual.w, expected.w);
+    rsDebug("float4 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v1.w", v1.w);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("v2.w", v2.w);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Dalvik result .w", expected.w);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("Renderscript result .w", actual.w);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+    rsDebug("ULP difference .w", dist.w);
+}
+
+static bool f1_almost_equal(float a, float b) {
+    return float_almost_equal(a, b);
+}
+
+static bool f2_almost_equal(float2 a, float2 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y);
+}
+
+
+static bool f3_almost_equal(float3 a, float3 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z);
+}
+
+static bool f4_almost_equal(float4 a, float4 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w);
+}
+
+#define TEST_BASIC_FLOAT_OP(op, opName)                 \
+temp_f1 = x op y;                                       \
+if (! float_almost_equal(temp_f1, result_##opName)) {   \
+    fail_f1(x, y , temp_f1, result_##opName, #opName);  \
+    failed = true;                                      \
+}
+
+#define TEST_FN_FN(func, size)                                                  \
+temp_f##size = func(rand_f##size##_0, rand_f##size##_1);                        \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) {   \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func);   \
+    failed = true;                                                              \
+}
+#define TEST_FN_F(func, size)                                               \
+temp_f##size = func(rand_f##size##_0, rand_f1_1);                           \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) {    \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func);   \
+    failed = true;                                                          \
+}
+
+#define TEST_FN_FN_ALL(func)    \
+TEST_FN_FN(func, 1)             \
+TEST_FN_FN(func, 2)             \
+TEST_FN_FN(func, 3)             \
+TEST_FN_FN(func, 4)
+#define TEST_FN_F_ALL(func) \
+TEST_FN_F(func, 2)          \
+TEST_FN_F(func, 3)          \
+TEST_FN_F(func, 4)
+
+#define TEST_VEC1_VEC1(func, type)                              \
+temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 );    \
+if (temp_##type##1 != func##_rand_##type##1_##type##1) {        \
+    rsDebug(#func " " #type "1 operation did not match!", 0);   \
+    rsDebug("v1", rand_##type##1_0);                            \
+    rsDebug("v2", rand_##type##1_1);                            \
+    rsDebug("Dalvik result", func##_rand_##type##1_##type##1);  \
+    rsDebug("Renderscript result", temp_##type##1);             \
+    failed = true;                                              \
+}
+#define TEST_VEC2_VEC2(func, type)                                      \
+temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 );            \
+if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x             \
+        || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) {   \
+    rsDebug(#func " " #type "2 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##2_0 .x);                               \
+    rsDebug("v1.y", rand_##type##2_0 .y);                               \
+    rsDebug("v2.x", rand_##type##2_1 .x);                               \
+    rsDebug("v2.y", rand_##type##2_1 .y);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y);    \
+    rsDebug("Renderscript result .x", temp_##type##2 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##2 .y);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC3_VEC3(func, type)                                      \
+temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 );            \
+if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x             \
+        || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y      \
+        || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) {   \
+    rsDebug(#func " " #type "3 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##3_0 .x);                               \
+    rsDebug("v1.y", rand_##type##3_0 .y);                               \
+    rsDebug("v1.z", rand_##type##3_0 .z);                               \
+    rsDebug("v2.x", rand_##type##3_1 .x);                               \
+    rsDebug("v2.y", rand_##type##3_1 .y);                               \
+    rsDebug("v2.z", rand_##type##3_1 .z);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z);    \
+    rsDebug("Renderscript result .x", temp_##type##3 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##3 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##3 .z);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC4_VEC4(func, type)                                      \
+temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 );            \
+if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x             \
+        || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y      \
+        || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z      \
+        || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) {   \
+    rsDebug(#func " " #type "4 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##4_0 .x);                               \
+    rsDebug("v1.y", rand_##type##4_0 .y);                               \
+    rsDebug("v1.z", rand_##type##4_0 .z);                               \
+    rsDebug("v1.w", rand_##type##4_0 .w);                               \
+    rsDebug("v2.x", rand_##type##4_1 .x);                               \
+    rsDebug("v2.y", rand_##type##4_1 .y);                               \
+    rsDebug("v2.z", rand_##type##4_1 .z);                               \
+    rsDebug("v2.w", rand_##type##4_1 .w);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z);    \
+    rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w);    \
+    rsDebug("Renderscript result .x", temp_##type##4 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##4 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##4 .z);               \
+    rsDebug("Renderscript result .w", temp_##type##4 .w);               \
+    failed = true;                                                      \
+}
+
+#define TEST_SC1_SC1(func)  TEST_VEC1_VEC1(func, sc)
+#define TEST_SC2_SC2(func)  TEST_VEC2_VEC2(func, sc)
+#define TEST_SC3_SC3(func)  TEST_VEC3_VEC3(func, sc)
+#define TEST_SC4_SC4(func)  TEST_VEC4_VEC4(func, sc)
+
+#define TEST_UC1_UC1(func)  TEST_VEC1_VEC1(func, uc)
+#define TEST_UC2_UC2(func)  TEST_VEC2_VEC2(func, uc)
+#define TEST_UC3_UC3(func)  TEST_VEC3_VEC3(func, uc)
+#define TEST_UC4_UC4(func)  TEST_VEC4_VEC4(func, uc)
+
+#define TEST_SS1_SS1(func)  TEST_VEC1_VEC1(func, ss)
+#define TEST_SS2_SS2(func)  TEST_VEC2_VEC2(func, ss)
+#define TEST_SS3_SS3(func)  TEST_VEC3_VEC3(func, ss)
+#define TEST_SS4_SS4(func)  TEST_VEC4_VEC4(func, ss)
+
+#define TEST_US1_US1(func)  TEST_VEC1_VEC1(func, us)
+#define TEST_US2_US2(func)  TEST_VEC2_VEC2(func, us)
+#define TEST_US3_US3(func)  TEST_VEC3_VEC3(func, us)
+#define TEST_US4_US4(func)  TEST_VEC4_VEC4(func, us)
+
+#define TEST_SI1_SI1(func)  TEST_VEC1_VEC1(func, si)
+#define TEST_SI2_SI2(func)  TEST_VEC2_VEC2(func, si)
+#define TEST_SI3_SI3(func)  TEST_VEC3_VEC3(func, si)
+#define TEST_SI4_SI4(func)  TEST_VEC4_VEC4(func, si)
+
+#define TEST_UI1_UI1(func)  TEST_VEC1_VEC1(func, ui)
+#define TEST_UI2_UI2(func)  TEST_VEC2_VEC2(func, ui)
+#define TEST_UI3_UI3(func)  TEST_VEC3_VEC3(func, ui)
+#define TEST_UI4_UI4(func)  TEST_VEC4_VEC4(func, ui)
+
+#define TEST_SL1_SL1(func)  TEST_VEC1_VEC1(func, sl)
+#define TEST_SL2_SL2(func)  TEST_VEC2_VEC2(func, sl)
+#define TEST_SL3_SL3(func)  TEST_VEC3_VEC3(func, sl)
+#define TEST_SL4_SL4(func)  TEST_VEC4_VEC4(func, sl)
+
+#define TEST_UL1_UL1(func)  TEST_VEC1_VEC1(func, ul)
+#define TEST_UL2_UL2(func)  TEST_VEC2_VEC2(func, ul)
+#define TEST_UL3_UL3(func)  TEST_VEC3_VEC3(func, ul)
+#define TEST_UL4_UL4(func)  TEST_VEC4_VEC4(func, ul)
+
+#define TEST_SC_SC_ALL(func)    \
+TEST_SC1_SC1(func)              \
+TEST_SC2_SC2(func)              \
+TEST_SC3_SC3(func)              \
+TEST_SC4_SC4(func)
+#define TEST_UC_UC_ALL(func)    \
+TEST_UC1_UC1(func)              \
+TEST_UC2_UC2(func)              \
+TEST_UC3_UC3(func)              \
+TEST_UC4_UC4(func)
+
+#define TEST_SS_SS_ALL(func)    \
+TEST_SS1_SS1(func)              \
+TEST_SS2_SS2(func)              \
+TEST_SS3_SS3(func)              \
+TEST_SS4_SS4(func)
+#define TEST_US_US_ALL(func)    \
+TEST_US1_US1(func)              \
+TEST_US2_US2(func)              \
+TEST_US3_US3(func)              \
+TEST_US4_US4(func)
+#define TEST_SI_SI_ALL(func)    \
+TEST_SI1_SI1(func)              \
+TEST_SI2_SI2(func)              \
+TEST_SI3_SI3(func)              \
+TEST_SI4_SI4(func)
+#define TEST_UI_UI_ALL(func)    \
+TEST_UI1_UI1(func)              \
+TEST_UI2_UI2(func)              \
+TEST_UI3_UI3(func)              \
+TEST_UI4_UI4(func)
+#define TEST_SL_SL_ALL(func)    \
+TEST_SL1_SL1(func)              \
+TEST_SL2_SL2(func)              \
+TEST_SL3_SL3(func)              \
+TEST_SL4_SL4(func)
+#define TEST_UL_UL_ALL(func)    \
+TEST_UL1_UL1(func)              \
+TEST_UL2_UL2(func)              \
+TEST_UL3_UL3(func)              \
+TEST_UL4_UL4(func)
+
+#define TEST_VEC_VEC_ALL(func)  \
+TEST_FN_FN_ALL(func)            \
+TEST_SC_SC_ALL(func)            \
+TEST_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
+TEST_UI_UI_ALL(func)
+
+// TODO:  add long types to ALL macro
+#if 0
+TEST_SL_SL_ALL(func)            \
+TEST_UL_UL_ALL(func)
+#endif
+
+#define DECLARE_TEMP_SET(type, abbrev)  \
+volatile type    temp_##abbrev##1;               \
+volatile type##2 temp_##abbrev##2;               \
+volatile type##3 temp_##abbrev##3;               \
+volatile type##4 temp_##abbrev##4;
+
+#define DECLARE_ALL_TEMP_SETS() \
+DECLARE_TEMP_SET(float, f);     \
+DECLARE_TEMP_SET(char, sc);     \
+DECLARE_TEMP_SET(uchar, uc);    \
+DECLARE_TEMP_SET(short, ss);    \
+DECLARE_TEMP_SET(ushort, us);   \
+DECLARE_TEMP_SET(int, si);      \
+DECLARE_TEMP_SET(uint, ui);     \
+DECLARE_TEMP_SET(long, sl);     \
+DECLARE_TEMP_SET(ulong, ul);
+
+static bool test_math_agree() {
+    bool failed = false;
+
+    DECLARE_ALL_TEMP_SETS();
+
+    TEST_BASIC_FLOAT_OP(+, add);
+    TEST_BASIC_FLOAT_OP(-, sub);
+    TEST_BASIC_FLOAT_OP(*, mul);
+    TEST_BASIC_FLOAT_OP(/, div);
+
+    TEST_VEC_VEC_ALL(min);
+    TEST_VEC_VEC_ALL(max);
+    TEST_FN_FN_ALL(fmin);
+    TEST_FN_F_ALL(fmin);
+    TEST_FN_FN_ALL(fmax);
+    TEST_FN_F_ALL(fmax);
+
+    if (failed) {
+        rsDebug("test_math_agree FAILED", 0);
+    }
+    else {
+        rsDebug("test_math_agree PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_agree_test() {
+    bool failed = false;
+    failed |= test_math_agree();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs
new file mode 100644
index 0000000..2d62f34
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs
@@ -0,0 +1,57 @@
+#include "shared.rsh"
+
+// Testing math conformance
+
+static bool test_rootn() {
+    bool failed = false;
+
+    // rootn(x, 0) -> NaN
+    _RS_ASSERT(isnan(rootn(1.0f, 0)));
+
+    // rootn(+/-0, n) -> +/-inf for odd n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -3)));
+    _RS_ASSERT(isneginf(rootn(-0.f, -3)));
+
+    // rootn(+/-0, n) -> +inf for even n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -8)));
+    _RS_ASSERT(isposinf(rootn(-0.f, -8)));
+
+    // rootn(+/-0, n) -> +/-0 for odd n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 3)));
+    _RS_ASSERT(isnegzero(rootn(-0.f, 3)));
+
+    // rootn(+/-0, n) -> +0 for even n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 8)));
+    _RS_ASSERT(isposzero(rootn(-0.f, 8)));
+
+    // rootn(x, n) -> NaN for x < 0 and even n
+    _RS_ASSERT(isnan(rootn(-10000.f, -4)));
+    _RS_ASSERT(isnan(rootn(-10000.f, 4)));
+
+    // rootn(x, n) -> value for x < 0 and odd n
+    _RS_ASSERT(!isnan(rootn(-10000.f, -3)));
+    _RS_ASSERT(!isnan(rootn(-10000.f, 3)));
+
+    if (failed) {
+        rsDebug("test_rootn FAILED", -1);
+    }
+    else {
+        rsDebug("test_rootn PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_conformance_test() {
+    bool failed = false;
+    failed |= test_rootn();
+
+    if (failed) {
+        rsDebug("math_conformance_test FAILED", -1);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("math_conformance_test PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/min.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/min.rs
new file mode 100644
index 0000000..4b92763
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/min.rs
@@ -0,0 +1,20 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+volatile uchar2 res_uc_2 = 1;
+volatile uchar2 src1_uc_2 = 1;
+volatile uchar2 src2_uc_2 = 1;
+
+void min_test() {
+    bool failed = false;
+
+    res_uc_2 = min(src1_uc_2, src2_uc_2);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
new file mode 100644
index 0000000..2c807bd
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
@@ -0,0 +1,45 @@
+#include "shared.rsh"
+
+rs_allocation aRaw;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    *out = 99 + x + y * dimX;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void noroot_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..ce451da
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool test_primitive_types(uint32_t index) {
+    bool failed = false;
+    start();
+
+    _RS_ASSERT(floatTest == 2.99f);
+    _RS_ASSERT(doubleTest == 3.05);
+    _RS_ASSERT(charTest == -16);
+    _RS_ASSERT(shortTest == -32);
+    _RS_ASSERT(intTest == -64);
+    _RS_ASSERT(longTest == 17179869185l);
+    _RS_ASSERT(longlongTest == 68719476735l);
+
+    _RS_ASSERT(ucharTest == 8);
+    _RS_ASSERT(ushortTest == 16);
+    _RS_ASSERT(uintTest == 32);
+    _RS_ASSERT(ulongTest == 4611686018427387903L);
+    _RS_ASSERT(int64_tTest == -17179869184l);
+    _RS_ASSERT(uint64_tTest == 117179869185l);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_primitives FAILED", time);
+    }
+    else {
+        rsDebug("test_primitives PASSED", time);
+    }
+
+    return failed;
+}
+
+void primitives_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_primitive_types(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs
new file mode 100644
index 0000000..4ea70e2
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs
@@ -0,0 +1,13 @@
+#include "shared.rsh"
+
+// Testing reference counting of RS object types
+
+rs_allocation globalA;
+static rs_allocation staticGlobalA;
+
+void refcount_test() {
+    staticGlobalA = globalA;
+    rsClearObject(&globalA);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs
new file mode 100644
index 0000000..68ac168
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs
@@ -0,0 +1,62 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+float2 float2Test = {2.99f, 12.99f};
+float3 float3Test = {3.99f, 13.99f, 23.99f};
+float4 float4Test = {4.99f, 14.99f, 24.99f, 34.99f};
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    // For this reason, none of the outputs are actually checked.
+
+    rsDebug("floatTest", floatTest);
+    rsDebug("float2Test", float2Test);
+    rsDebug("float3Test", float3Test);
+    rsDebug("float4Test", float4Test);
+    rsDebug("doubleTest", doubleTest);
+    rsDebug("charTest", charTest);
+    rsDebug("shortTest", shortTest);
+    rsDebug("intTest", intTest);
+    rsDebug("longTest", longTest);
+    rsDebug("longlongTest", longlongTest);
+
+    rsDebug("ucharTest", ucharTest);
+    rsDebug("ushortTest", ushortTest);
+    rsDebug("uintTest", uintTest);
+    rsDebug("ulongTest", ulongTest);
+    rsDebug("int64_tTest", int64_tTest);
+    rsDebug("uint64_tTest", uint64_tTest);
+
+    return failed;
+}
+
+void test_rsdebug(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rsdebug_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rsdebug_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..650243e
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,25 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..7be955d
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (since we set America/Los_Angeles localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs
new file mode 100644
index 0000000..bec124d
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element elementTest;
+rs_type typeTest;
+rs_allocation allocationTest;
+rs_sampler samplerTest;
+rs_script scriptTest;
+
+rs_matrix4x4 matrix4x4Test;
+rs_matrix3x3 matrix3x3Test;
+rs_matrix2x2 matrix2x2Test;
+
+struct my_struct {
+    int i;
+    rs_allocation banana;
+};
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_matrix4x4 matrix4x4TestLocal;
+    rs_matrix3x3 matrix3x3TestLocal;
+    rs_matrix2x2 matrix2x2TestLocal;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    rs_element elementTestLocal;
+    rs_type typeTestLocal;
+    rs_allocation allocationTestLocal;
+    rs_sampler samplerTestLocal;
+    rs_script scriptTestLocal;
+
+    struct my_struct structTest;
+
+    //allocationTestLocal = allocationTest;
+
+    //allocationTest = allocationTestLocal;
+
+    /*for (int i = 0; i < 4; i++) {
+        fontTestLocalArray[i] = fontTestLocal;
+    }*/
+
+    /*fontTest = fontTestLocalArray[3];*/
+
+    return failed;
+}
+
+void test_rstypes(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstypes_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstypes_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs
new file mode 100644
index 0000000..ff1c0a7
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs
@@ -0,0 +1,63 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+rs_sampler minification;
+rs_sampler magnification;
+rs_sampler wrapS;
+rs_sampler wrapT;
+rs_sampler anisotropy;
+
+static bool test_sampler_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
+    _RS_ASSERT(rsSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(minification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
+    _RS_ASSERT(rsSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(magnification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapS) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapT) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(anisotropy) == 8.0f);
+
+    if (failed) {
+        rsDebug("test_sampler_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_sampler_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void sampler_test() {
+    bool failed = false;
+    failed |= test_sampler_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh b/java/tests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh
new file mode 100644
index 0000000..b05a354
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh
@@ -0,0 +1,114 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+static const int iposinf = 0x7f800000;
+static const int ineginf = 0xff800000;
+
+static const float posinf() {
+    float f = *((float*)&iposinf);
+    return f;
+}
+
+static const float neginf() {
+    float f = *((float*)&ineginf);
+    return f;
+}
+
+static bool isposinf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == iposinf);
+}
+
+static bool isneginf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == ineginf);
+}
+
+static bool isnan(float f) {
+    int i = *((int*)(void*)&f);
+    return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff));
+}
+
+static bool isposzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x00000000);
+}
+
+static bool isnegzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x80000000);
+}
+
+static bool iszero(float f) {
+    return isposzero(f) || isnegzero(f);
+}
+
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/struct.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/struct.rs
new file mode 100644
index 0000000..1cd728e
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/struct.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+typedef struct Point2 {
+   int x;
+   int y;
+} Point_2;
+Point_2 *point2;
+
+static bool test_Point_2(int expected) {
+    bool failed = false;
+
+    rsDebug("Point: ", point2[0].x, point2[0].y);
+    _RS_ASSERT(point2[0].x == expected);
+    _RS_ASSERT(point2[0].y == expected);
+
+    if (failed) {
+        rsDebug("test_Point_2 FAILED", 0);
+    }
+    else {
+        rsDebug("test_Point_2 PASSED", 0);
+    }
+
+    return failed;
+}
+
+void struct_test(int expected) {
+    bool failed = false;
+    failed |= test_Point_2(expected);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs
new file mode 100644
index 0000000..89e7de7
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs
@@ -0,0 +1,23 @@
+// Fountain test script
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+#pragma stateFragment(parent)
+
+#include "rs_graphics.rsh"
+
+
+typedef struct TestResult {
+    rs_allocation name;
+    bool pass;
+    float score;
+} TestResult_t;
+TestResult_t *results;
+
+int root() {
+
+    return 0;
+}
+
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs
new file mode 100644
index 0000000..2c056f4
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs
@@ -0,0 +1,36 @@
+#include "shared.rsh"
+
+// Testing unsigned types for Bug 6764163
+unsigned int ui = 37;
+unsigned char uc = 5;
+
+static bool test_unsigned() {
+    bool failed = false;
+
+    rsDebug("ui", ui);
+    rsDebug("uc", uc);
+    _RS_ASSERT(ui == 0x7fffffff);
+    _RS_ASSERT(uc == 129);
+
+    if (failed) {
+        rsDebug("test_unsigned FAILED", -1);
+    }
+    else {
+        rsDebug("test_unsigned PASSED", 0);
+    }
+
+    return failed;
+}
+
+void unsigned_test() {
+    bool failed = false;
+    failed |= test_unsigned();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/vector.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/vector.rs
new file mode 100644
index 0000000..0430a2f
--- /dev/null
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/vector.rs
@@ -0,0 +1,198 @@
+#include "shared.rsh"
+
+// Testing vector types
+float2 f2 = { 1.0f, 2.0f };
+float3 f3 = { 1.0f, 2.0f, 3.0f };
+float4 f4 = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+double2 d2 = { 1.0, 2.0 };
+double3 d3 = { 1.0, 2.0, 3.0 };
+double4 d4 = { 1.0, 2.0, 3.0, 4.0 };
+
+char2 i8_2 = { 1, 2 };
+char3 i8_3 = { 1, 2, 3 };
+char4 i8_4 = { 1, 2, 3, 4 };
+
+uchar2 u8_2 = { 1, 2 };
+uchar3 u8_3 = { 1, 2, 3 };
+uchar4 u8_4 = { 1, 2, 3, 4 };
+
+short2 i16_2 = { 1, 2 };
+short3 i16_3 = { 1, 2, 3 };
+short4 i16_4 = { 1, 2, 3, 4 };
+
+ushort2 u16_2 = { 1, 2 };
+ushort3 u16_3 = { 1, 2, 3 };
+ushort4 u16_4 = { 1, 2, 3, 4 };
+
+int2 i32_2 = { 1, 2 };
+int3 i32_3 = { 1, 2, 3 };
+int4 i32_4 = { 1, 2, 3, 4 };
+
+uint2 u32_2 = { 1, 2 };
+uint3 u32_3 = { 1, 2, 3 };
+uint4 u32_4 = { 1, 2, 3, 4 };
+
+long2 i64_2 = { 1, 2 };
+long3 i64_3 = { 1, 2, 3 };
+long4 i64_4 = { 1, 2, 3, 4 };
+
+ulong2 u64_2 = { 1, 2 };
+ulong3 u64_3 = { 1, 2, 3 };
+ulong4 u64_4 = { 1, 2, 3, 4 };
+
+static bool test_vector_types() {
+    bool failed = false;
+
+    rsDebug("Testing F32", 0);
+    _RS_ASSERT(f2.x == 2.99f);
+    _RS_ASSERT(f2.y == 3.99f);
+
+    _RS_ASSERT(f3.x == 2.99f);
+    _RS_ASSERT(f3.y == 3.99f);
+    _RS_ASSERT(f3.z == 4.99f);
+
+    _RS_ASSERT(f4.x == 2.99f);
+    _RS_ASSERT(f4.y == 3.99f);
+    _RS_ASSERT(f4.z == 4.99f);
+    _RS_ASSERT(f4.w == 5.99f);
+
+    rsDebug("Testing F64", 0);
+    _RS_ASSERT(d2.x == 2.99);
+    _RS_ASSERT(d2.y == 3.99);
+
+    _RS_ASSERT(d3.x == 2.99);
+    _RS_ASSERT(d3.y == 3.99);
+    _RS_ASSERT(d3.z == 4.99);
+
+    _RS_ASSERT(d4.x == 2.99);
+    _RS_ASSERT(d4.y == 3.99);
+    _RS_ASSERT(d4.z == 4.99);
+    _RS_ASSERT(d4.w == 5.99);
+
+    rsDebug("Testing I8", 0);
+    _RS_ASSERT(i8_2.x == 2);
+    _RS_ASSERT(i8_2.y == 3);
+
+    _RS_ASSERT(i8_3.x == 2);
+    _RS_ASSERT(i8_3.y == 3);
+    _RS_ASSERT(i8_3.z == 4);
+
+    _RS_ASSERT(i8_4.x == 2);
+    _RS_ASSERT(i8_4.y == 3);
+    _RS_ASSERT(i8_4.z == 4);
+    _RS_ASSERT(i8_4.w == 5);
+
+    rsDebug("Testing U8", 0);
+    _RS_ASSERT(u8_2.x == 2);
+    _RS_ASSERT(u8_2.y == 3);
+
+    _RS_ASSERT(u8_3.x == 2);
+    _RS_ASSERT(u8_3.y == 3);
+    _RS_ASSERT(u8_3.z == 4);
+
+    _RS_ASSERT(u8_4.x == 2);
+    _RS_ASSERT(u8_4.y == 3);
+    _RS_ASSERT(u8_4.z == 4);
+    _RS_ASSERT(u8_4.w == 5);
+
+    rsDebug("Testing I16", 0);
+    _RS_ASSERT(i16_2.x == 2);
+    _RS_ASSERT(i16_2.y == 3);
+
+    _RS_ASSERT(i16_3.x == 2);
+    _RS_ASSERT(i16_3.y == 3);
+    _RS_ASSERT(i16_3.z == 4);
+
+    _RS_ASSERT(i16_4.x == 2);
+    _RS_ASSERT(i16_4.y == 3);
+    _RS_ASSERT(i16_4.z == 4);
+    _RS_ASSERT(i16_4.w == 5);
+
+    rsDebug("Testing U16", 0);
+    _RS_ASSERT(u16_2.x == 2);
+    _RS_ASSERT(u16_2.y == 3);
+
+    _RS_ASSERT(u16_3.x == 2);
+    _RS_ASSERT(u16_3.y == 3);
+    _RS_ASSERT(u16_3.z == 4);
+
+    _RS_ASSERT(u16_4.x == 2);
+    _RS_ASSERT(u16_4.y == 3);
+    _RS_ASSERT(u16_4.z == 4);
+    _RS_ASSERT(u16_4.w == 5);
+
+    rsDebug("Testing I32", 0);
+    _RS_ASSERT(i32_2.x == 2);
+    _RS_ASSERT(i32_2.y == 3);
+
+    _RS_ASSERT(i32_3.x == 2);
+    _RS_ASSERT(i32_3.y == 3);
+    _RS_ASSERT(i32_3.z == 4);
+
+    _RS_ASSERT(i32_4.x == 2);
+    _RS_ASSERT(i32_4.y == 3);
+    _RS_ASSERT(i32_4.z == 4);
+    _RS_ASSERT(i32_4.w == 5);
+
+    rsDebug("Testing U32", 0);
+    _RS_ASSERT(u32_2.x == 2);
+    _RS_ASSERT(u32_2.y == 3);
+
+    _RS_ASSERT(u32_3.x == 2);
+    _RS_ASSERT(u32_3.y == 3);
+    _RS_ASSERT(u32_3.z == 4);
+
+    _RS_ASSERT(u32_4.x == 2);
+    _RS_ASSERT(u32_4.y == 3);
+    _RS_ASSERT(u32_4.z == 4);
+    _RS_ASSERT(u32_4.w == 5);
+
+    rsDebug("Testing I64", 0);
+    _RS_ASSERT(i64_2.x == 2);
+    _RS_ASSERT(i64_2.y == 3);
+
+    _RS_ASSERT(i64_3.x == 2);
+    _RS_ASSERT(i64_3.y == 3);
+    _RS_ASSERT(i64_3.z == 4);
+
+    _RS_ASSERT(i64_4.x == 2);
+    _RS_ASSERT(i64_4.y == 3);
+    _RS_ASSERT(i64_4.z == 4);
+    _RS_ASSERT(i64_4.w == 5);
+
+    rsDebug("Testing U64", 0);
+    _RS_ASSERT(u64_2.x == 2);
+    _RS_ASSERT(u64_2.y == 3);
+
+    _RS_ASSERT(u64_3.x == 2);
+    _RS_ASSERT(u64_3.y == 3);
+    _RS_ASSERT(u64_3.z == 4);
+
+    _RS_ASSERT(u64_4.x == 2);
+    _RS_ASSERT(u64_4.y == 3);
+    _RS_ASSERT(u64_4.z == 4);
+    _RS_ASSERT(u64_4.w == 5);
+
+    if (failed) {
+        rsDebug("test_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void vector_test() {
+    bool failed = false;
+    failed |= test_vector_types();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/Android.mk b/java/tests/RsTest/Android.mk
new file mode 100644
index 0000000..198693c
--- /dev/null
+++ b/java/tests/RsTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RSTest
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/RsTest/AndroidManifest.xml b/java/tests/RsTest/AndroidManifest.xml
new file mode 100644
index 0000000..b660398
--- /dev/null
+++ b/java/tests/RsTest/AndroidManifest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.test">
+    <application 
+        android:label="_RS_Test"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="RSTest"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/RsTest/res/drawable-nodpi/test_pattern.png b/java/tests/RsTest/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/java/tests/RsTest/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/java/tests/RsTest/src/com/android/rs/test/RSTest.java b/java/tests/RsTest/src/com/android/rs/test/RSTest.java
new file mode 100644
index 0000000..d1b23fa
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/RSTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import java.lang.Runtime;
+
+public class RSTest extends Activity {
+    //EventListener mListener = new EventListener();
+
+    private static final String LOG_TAG = "RSTest";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private RSTestView mView;
+
+    // get the current looper (from your Activity UI thread for instance
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new RSTestView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onPause();
+        mView.pause();
+    }
+
+    @Override
+    protected void onStop() {
+        // Actually kill the app if we are stopping. We don't want to
+        // continue/resume this test ever. It should always start fresh.
+        finish();
+        super.onStop();
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java b/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java
new file mode 100644
index 0000000..8645ae5
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java
@@ -0,0 +1,236 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+public class RSTestCore {
+    int mWidth;
+    int mHeight;
+    Context mCtx;
+
+    public RSTestCore(Context ctx) {
+        mCtx = ctx;
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private Font mFont;
+    ScriptField_ListAllocs_s mListAllocs;
+    int mLastX;
+    int mLastY;
+    private ScriptC_rslist mScript;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        mWidth = width;
+        mHeight = height;
+        stopTesting = false;
+
+        mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist);
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_constant(this, mRes, mCtx));
+        unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_unsigned(this, mRes, mCtx));
+        unitTests.add(new UT_array_init(this, mRes, mCtx));
+        unitTests.add(new UT_array_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_kernel(this, mRes, mCtx));
+        unitTests.add(new UT_kernel_struct(this, mRes, mCtx));
+        unitTests.add(new UT_bug_char(this, mRes, mCtx));
+        unitTests.add(new UT_clamp(this, mRes, mCtx));
+        unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_convert(this, mRes, mCtx));
+        unitTests.add(new UT_convert_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_copy_test(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_refcount(this, mRes, mCtx));
+        unitTests.add(new UT_foreach(this, mRes, mCtx));
+        unitTests.add(new UT_foreach_bounds(this, mRes, mCtx));
+        unitTests.add(new UT_noroot(this, mRes, mCtx));
+        unitTests.add(new UT_atomic(this, mRes, mCtx));
+        unitTests.add(new UT_struct(this, mRes, mCtx));
+        unitTests.add(new UT_math(this, mRes, mCtx));
+        unitTests.add(new UT_math_conformance(this, mRes, mCtx));
+        unitTests.add(new UT_math_agree(this, mRes, mCtx));
+        unitTests.add(new UT_min(this, mRes, mCtx));
+        unitTests.add(new UT_int4(this, mRes, mCtx));
+        unitTests.add(new UT_element(this, mRes, mCtx));
+        unitTests.add(new UT_sampler(this, mRes, mCtx));
+        unitTests.add(new UT_program_store(this, mRes, mCtx));
+        unitTests.add(new UT_program_raster(this, mRes, mCtx));
+        unitTests.add(new UT_mesh(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
+
+        /*
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
+        unitTests.add(new UnitTest());
+        unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+        for (int i = 0; i < 20; i++) {
+            unitTests.add(new UnitTest(null, "<Pass>", 1));
+        }
+        */
+
+        UnitTest [] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].getResult();
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+
+        mScript.bind_gList(mListAllocs);
+
+        mFont = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mScript.set_gFont(mFont);
+
+        mRS.bindRootScript(mScript);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                }
+                catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            }
+            else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+
+        if (mListAllocs != null && mScript != null && mRS != null) {
+            mListAllocs.copyAll();
+
+            mScript.bind_gList(mListAllocs);
+            mRS.bindRootScript(mScript);
+        }
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+    public void newTouchPosition(float x, float y, float pressure, int id) {
+    }
+
+    public void onActionDown(int x, int y) {
+        mScript.set_gDY(0.0f);
+        mLastX = x;
+        mLastY = y;
+        refreshTestResults();
+    }
+
+    public void onActionMove(int x, int y) {
+        int dx = mLastX - x;
+        int dy = mLastY - y;
+
+        if (Math.abs(dy) <= 2) {
+            dy = 0;
+        }
+
+        mScript.set_gDY(dy);
+
+        mLastX = x;
+        mLastY = y;
+        refreshTestResults();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/RSTestView.java b/java/tests/RsTest/src/com/android/rs/test/RSTestView.java
new file mode 100644
index 0000000..368f286
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/RSTestView.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.rs.test;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class RSTestView extends RSSurfaceView {
+
+    private Context mCtx;
+
+    public RSTestView(Context context) {
+        super(context);
+        mCtx = context;
+        //setFocusable(true);
+    }
+
+    private RenderScriptGL mRS;
+    private RSTestCore mRender;
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRS = createRenderScriptGL(sc);
+            mRS.setSurface(holder, w, h);
+            mRender = new RSTestCore(mCtx);
+            mRender.init(mRS, getResources(), w, h);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if(mRS != null) {
+            mRender.cleanup();
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev)
+    {
+        boolean ret = false;
+        int act = ev.getAction();
+        if (act == ev.ACTION_DOWN) {
+            mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+            ret = true;
+        }
+        else if (act == ev.ACTION_MOVE) {
+            mRender.onActionMove((int)ev.getX(), (int)ev.getY());
+            ret = true;
+        }
+
+        return ret;
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_alloc.java b/java/tests/RsTest/src/com/android/rs/test/UT_alloc.java
new file mode 100644
index 0000000..3ea942c
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_alloc.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Alloc", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_alloc s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        int Z = 0;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        s.set_dimZ(Z);
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+        s.set_aRaw(A);
+
+        typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        typeBuilder.setX(X).setY(Y).setFaces(true);
+        Allocation AFaces = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFaces(AFaces);
+        typeBuilder.setFaces(false).setMipmaps(true);
+        Allocation ALOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aLOD(ALOD);
+        typeBuilder.setFaces(true).setMipmaps(true);
+        Allocation AFacesLOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFacesLOD(AFacesLOD);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_alloc s = new ScriptC_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(s.get_aRaw());
+        s.invoke_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_array_alloc.java b/java/tests/RsTest/src/com/android/rs/test/UT_array_alloc.java
new file mode 100644
index 0000000..ac01a93
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_array_alloc.java
@@ -0,0 +1,52 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_array_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Allocation", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_alloc s = new ScriptC_array_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        int dimX = s.get_dimX();
+        Allocation[] Arr = new Allocation[dimX];
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.I32(pRS));
+        Type T = typeBuilder.setX(1).create();
+        for (int i = 0; i < dimX; i++) {
+            Allocation A = Allocation.createTyped(pRS, T);
+            Arr[i] = A;
+        }
+        s.set_a(Arr);
+
+        s.invoke_array_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_array_init.java b/java/tests/RsTest/src/com/android/rs/test/UT_array_init.java
new file mode 100644
index 0000000..c74e4b3
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_array_init.java
@@ -0,0 +1,95 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_array_init extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_init(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Init", ctx);
+        mRes = res;
+    }
+
+    private void checkInit(ScriptC_array_init s) {
+        float[] fa = s.get_fa();
+        _RS_ASSERT("fa[0] == 1.0", fa[0] == 1.0);
+        _RS_ASSERT("fa[1] == 9.9999f", fa[1] == 9.9999f);
+        _RS_ASSERT("fa[2] == 0", fa[2] == 0);
+        _RS_ASSERT("fa[3] == 0", fa[3] == 0);
+        _RS_ASSERT("fa.length == 4", fa.length == 4);
+
+        double[] da = s.get_da();
+        _RS_ASSERT("da[0] == 7.0", da[0] == 7.0);
+        _RS_ASSERT("da[1] == 8.88888", da[1] == 8.88888);
+        _RS_ASSERT("da.length == 2", da.length == 2);
+
+        byte[] ca = s.get_ca();
+        _RS_ASSERT("ca[0] == 'a'", ca[0] == 'a');
+        _RS_ASSERT("ca[1] == 7", ca[1] == 7);
+        _RS_ASSERT("ca[2] == 'b'", ca[2] == 'b');
+        _RS_ASSERT("ca[3] == 'c'", ca[3] == 'c');
+        _RS_ASSERT("ca.length == 4", ca.length == 4);
+
+        short[] sa = s.get_sa();
+        _RS_ASSERT("sa[0] == 1", sa[0] == 1);
+        _RS_ASSERT("sa[1] == 1", sa[1] == 1);
+        _RS_ASSERT("sa[2] == 2", sa[2] == 2);
+        _RS_ASSERT("sa[3] == 3", sa[3] == 3);
+        _RS_ASSERT("sa.length == 4", sa.length == 4);
+
+        int[] ia = s.get_ia();
+        _RS_ASSERT("ia[0] == 5", ia[0] == 5);
+        _RS_ASSERT("ia[1] == 8", ia[1] == 8);
+        _RS_ASSERT("ia[2] == 0", ia[2] == 0);
+        _RS_ASSERT("ia[3] == 0", ia[3] == 0);
+        _RS_ASSERT("ia.length == 4", ia.length == 4);
+
+        long[] la = s.get_la();
+        _RS_ASSERT("la[0] == 13", la[0] == 13);
+        _RS_ASSERT("la[1] == 21", la[1] == 21);
+        _RS_ASSERT("la.length == 4", la.length == 2);
+
+        long[] lla = s.get_lla();
+        _RS_ASSERT("lla[0] == 34", lla[0] == 34);
+        _RS_ASSERT("lla[1] == 0", lla[1] == 0);
+        _RS_ASSERT("lla[2] == 0", lla[2] == 0);
+        _RS_ASSERT("lla[3] == 0", lla[3] == 0);
+        _RS_ASSERT("lla.length == 4", lla.length == 4);
+
+        boolean[] ba = s.get_ba();
+        _RS_ASSERT("ba[0] == true", ba[0] == true);
+        _RS_ASSERT("ba[1] == false", ba[1] == false);
+        _RS_ASSERT("ba[2] == false", ba[2] == false);
+        _RS_ASSERT("ba.length == 3", ba.length == 3);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_init s = new ScriptC_array_init(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        checkInit(s);
+        s.invoke_array_init_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_atomic.java b/java/tests/RsTest/src/com/android/rs/test/UT_atomic.java
new file mode 100644
index 0000000..0b8e072
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_atomic.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_atomic extends UnitTest {
+    private Resources mRes;
+
+    protected UT_atomic(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Atomics", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_atomic s = new ScriptC_atomic(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_atomic_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_bug_char.java b/java/tests/RsTest/src/com/android/rs/test/UT_bug_char.java
new file mode 100644
index 0000000..faf3a31
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_bug_char.java
@@ -0,0 +1,89 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+
+public class UT_bug_char extends UnitTest {
+    private Resources mRes;
+
+    protected UT_bug_char(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Bug Char", ctx);
+        mRes = res;
+    }
+
+    // packing functions
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        Log.i("bug_char", "pack_b2 " + val[0] + " " + val[1]);
+        return new Byte2(val[0], val[1]);
+    }
+
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_bug_char s) {
+        byte rand_sc1_0 = (byte)7;
+        byte[] rand_sc2_0 = new byte[2];
+        rand_sc2_0[0] = 11;
+        rand_sc2_0[1] = 21;
+        Log.i("bug_char", "Generated sc2_0 to " + Arrays.toString(rand_sc2_0));
+        byte rand_sc1_1 = (byte)10;
+        byte[] rand_sc2_1 = new byte[2];
+        rand_sc2_1[0] = 13;
+        rand_sc2_1[1] = 15;
+        Log.i("bug_char", "Generated sc2_1 to " + Arrays.toString(rand_sc2_1));
+
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        // Set results for min
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        byte[] min_rand_sc2_raw = min(rand_sc2_0, rand_sc2_1);
+        Log.i("bug_char", "Generating min_rand_sc2_sc2 to " +
+              Arrays.toString(min_rand_sc2_raw));
+        Byte2 min_rand_sc2 = pack_b2(min_rand_sc2_raw);
+        Log.i("bug_char", "Setting min_rand_sc2_sc2 to [" + min_rand_sc2.x +
+              ", " + min_rand_sc2.y + "]");
+        s.set_min_rand_sc2_sc2(min_rand_sc2);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_bug_char s = new ScriptC_bug_char(pRS, mRes,
+                R.raw.bug_char);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_bug_char_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_clamp.java b/java/tests/RsTest/src/com/android/rs/test/UT_clamp.java
new file mode 100644
index 0000000..de98d0c
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_clamp.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_clamp extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Full)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp s = new ScriptC_clamp(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_clamp_relaxed.java b/java/tests/RsTest/src/com/android/rs/test/UT_clamp_relaxed.java
new file mode 100644
index 0000000..91e7140
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_clamp_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_clamp_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp_relaxed s =
+                new ScriptC_clamp_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_constant.java b/java/tests/RsTest/src/com/android/rs/test/UT_constant.java
new file mode 100644
index 0000000..adda5a3
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_constant.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_constant extends UnitTest {
+    private Resources mRes;
+
+    protected UT_constant(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Const", ctx);
+        mRes = res;
+    }
+
+    private void Assert(boolean b) {
+        if (!b) {
+            failTest();
+        }
+    }
+
+    public void run() {
+        Assert(ScriptC_constant.const_floatTest == 1.99f);
+        Assert(ScriptC_constant.const_doubleTest == 2.05);
+        Assert(ScriptC_constant.const_charTest == -8);
+        Assert(ScriptC_constant.const_shortTest == -16);
+        Assert(ScriptC_constant.const_intTest == -32);
+        Assert(ScriptC_constant.const_longTest == 17179869184l);
+        Assert(ScriptC_constant.const_longlongTest == 68719476736l);
+
+        Assert(ScriptC_constant.const_ucharTest == 8);
+        Assert(ScriptC_constant.const_ushortTest == 16);
+        Assert(ScriptC_constant.const_uintTest == 32);
+        Assert(ScriptC_constant.const_ulongTest == 4611686018427387904L);
+        Assert(ScriptC_constant.const_int64_tTest == -17179869184l);
+        Assert(ScriptC_constant.const_uint64_tTest == 117179869184l);
+
+        Assert(ScriptC_constant.const_boolTest == true);
+
+        passTest();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_convert.java b/java/tests/RsTest/src/com/android/rs/test/UT_convert.java
new file mode 100644
index 0000000..adf79bc
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_convert.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_convert extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert s = new ScriptC_convert(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_convert_relaxed.java b/java/tests/RsTest/src/com/android/rs/test/UT_convert_relaxed.java
new file mode 100644
index 0000000..a0757f3
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_convert_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_convert_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert_relaxed s =
+                new ScriptC_convert_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_copy_test.java b/java/tests/RsTest/src/com/android/rs/test/UT_copy_test.java
new file mode 100644
index 0000000..380f6ec
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_copy_test.java
@@ -0,0 +1,120 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_copy_test extends UnitTest {
+    private Resources mRes;
+    boolean pass = true;
+
+    protected UT_copy_test(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Copy", ctx);
+        mRes = res;
+    }
+
+    void testFloat2(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+
+        float[] f1 = new float[1024 * 2];
+        float[] f2 = new float[1024 * 2];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat2(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat3(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat3(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if ((f1[ct] != f2[ct]) && ((ct&3) != 3)) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat4(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat4(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_copy_test s = new ScriptC_copy_test(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        testFloat2(pRS, s);
+        testFloat3(pRS, s);
+        testFloat4(pRS, s);
+        s.invoke_sendResult(true);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_element.java b/java/tests/RsTest/src/com/android/rs/test/UT_element.java
new file mode 100644
index 0000000..07bcc74
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_element.java
@@ -0,0 +1,132 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Element.*;
+import android.renderscript.Element.DataKind.*;
+import android.renderscript.Element.DataType.*;
+
+public class UT_element extends UnitTest {
+    private Resources mRes;
+
+    Element simpleElem;
+    Element complexElem;
+
+    final String subElemNames[] = {
+        "subElem0",
+        "subElem1",
+        "subElem2",
+        "arrayElem0",
+        "arrayElem1",
+        "subElem3",
+        "subElem4",
+        "subElem5",
+        "subElem6",
+        "subElem_7",
+    };
+
+    final int subElemArraySizes[] = {
+        1,
+        1,
+        1,
+        2,
+        5,
+        1,
+        1,
+        1,
+        1,
+        1,
+    };
+
+    final int subElemOffsets[] = {
+        0,
+        4,
+        8,
+        12,
+        20,
+        40,
+        44,
+        48,
+        64,
+        80,
+    };
+
+    protected UT_element(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Element", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_element s) {
+        simpleElem = Element.F32_3(RS);
+        complexElem = ScriptField_ComplexStruct.createElement(RS);
+        s.set_simpleElem(simpleElem);
+        s.set_complexElem(complexElem);
+
+        ScriptField_ComplexStruct data = new ScriptField_ComplexStruct(RS, 1);
+        s.bind_complexStruct(data);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_element s = new ScriptC_element(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_element_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+
+        int subElemCount = simpleElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 0", subElemCount == 0);
+        _RS_ASSERT("simpleElem.getDataKind() == USER",
+                   simpleElem.getDataKind() == DataKind.USER);
+        _RS_ASSERT("simpleElem.getDataType() == FLOAT_32",
+                   simpleElem.getDataType() == DataType.FLOAT_32);
+
+        subElemCount = complexElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 10", subElemCount == 10);
+        _RS_ASSERT("complexElem.getDataKind() == USER",
+                   complexElem.getDataKind() == DataKind.USER);
+        _RS_ASSERT("complexElemsimpleElem.getDataType() == NONE",
+                   complexElem.getDataType() == DataType.NONE);
+        _RS_ASSERT("complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof",
+                   complexElem.getBytesSize() == ScriptField_ComplexStruct.Item.sizeof);
+
+        for (int i = 0; i < subElemCount; i ++) {
+            _RS_ASSERT("complexElem.getSubElement(i) != null",
+                       complexElem.getSubElement(i) != null);
+            _RS_ASSERT("complexElem.getSubElementName(i).equals(subElemNames[i])",
+                       complexElem.getSubElementName(i).equals(subElemNames[i]));
+            _RS_ASSERT("complexElem.getSubElementArraySize(i) == subElemArraySizes[i]",
+                       complexElem.getSubElementArraySize(i) == subElemArraySizes[i]);
+            _RS_ASSERT("complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]",
+                       complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]);
+        }
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_foreach.java b/java/tests/RsTest/src/com/android/rs/test/UT_foreach.java
new file mode 100644
index 0000000..6c95109
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_foreach.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_foreach extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach s = new ScriptC_foreach(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(A);
+        s.invoke_verify_root();
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_foreach_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_foreach_bounds.java b/java/tests/RsTest/src/com/android/rs/test/UT_foreach_bounds.java
new file mode 100644
index 0000000..97f3a32
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_foreach_bounds.java
@@ -0,0 +1,72 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_foreach_bounds extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach_bounds(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (bounds)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach_bounds s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        final int xStart = 2;
+        final int xEnd = 5;
+        final int yStart = 3;
+        final int yEnd = 6;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+        s.set_s(s);
+        s.set_ain(A);
+        s.set_aout(A);
+        s.set_xStart(xStart);
+        s.set_xEnd(xEnd);
+        s.set_yStart(yStart);
+        s.set_yEnd(yEnd);
+        s.forEach_zero(A);
+
+        Script.LaunchOptions sc = new Script.LaunchOptions();
+        sc.setX(xStart, xEnd).setY(yStart, yEnd);
+        s.forEach_root(A, sc);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach_bounds s = new ScriptC_foreach_bounds(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_verify_root();
+        s.invoke_foreach_bounds_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_fp_mad.java b/java/tests/RsTest/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..5b7344d
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+    private Resources mRes;
+
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_fp_mad_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_int4.java b/java/tests/RsTest/src/com/android/rs/test/UT_int4.java
new file mode 100644
index 0000000..89a2a71
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_int4.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_int4 extends UnitTest {
+    private Resources mRes;
+
+    protected UT_int4(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "int4", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_int4 s = new ScriptC_int4(pRS, mRes, R.raw.int4);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_int4_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_kernel.java b/java/tests/RsTest/src/com/android/rs/test/UT_kernel.java
new file mode 100644
index 0000000..e0bd33e
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_kernel.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        s.set_dimX(X);
+        typeBuilder.setX(X);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_ain(A);
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_aout(B);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel s = new ScriptC_kernel(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_kernel_struct.java b/java/tests/RsTest/src/com/android/rs/test/UT_kernel_struct.java
new file mode 100644
index 0000000..8e22810
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_kernel_struct.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel_struct extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (struct pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel_struct s) {
+        int X = 5;
+        s.set_dimX(X);
+        ScriptField_simpleStruct t;
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_ain(t);
+        A = t.getAllocation();
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_aout(t);
+        B = t.getAllocation();
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel_struct s = new ScriptC_kernel_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_struct_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_math.java b/java/tests/RsTest/src/com/android/rs/test/UT_math.java
new file mode 100644
index 0000000..8ad462b
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_math.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_math extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math s = new ScriptC_math(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_math_agree.java b/java/tests/RsTest/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..220509c
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,527 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Random;
+
+public class UT_math_agree extends UnitTest {
+    private Resources mRes;
+    private Random rand;
+
+    protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Agreement", ctx);
+        mRes = res;
+        rand = new Random();
+    }
+
+    // packing functions
+    private Float2 pack_f2(float[] val) {
+        assert val.length == 2;
+        return new Float2(val[0], val[1]);
+    }
+    private Float3 pack_f3(float[] val) {
+        assert val.length == 3;
+        return new Float3(val[0], val[1], val[2]);
+    }
+    private Float4 pack_f4(float[] val) {
+        assert val.length == 4;
+        return new Float4(val[0], val[1], val[2], val[3]);
+    }
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        return new Byte2(val[0], val[1]);
+    }
+    private Byte3 pack_b3(byte[] val) {
+        assert val.length == 3;
+        return new Byte3(val[0], val[1], val[2]);
+    }
+    private Byte4 pack_b4(byte[] val) {
+        assert val.length == 4;
+        return new Byte4(val[0], val[1], val[2], val[3]);
+    }
+    private Short2 pack_s2(short[] val) {
+        assert val.length == 2;
+        return new Short2(val[0], val[1]);
+    }
+    private Short3 pack_s3(short[] val) {
+        assert val.length == 3;
+        return new Short3(val[0], val[1], val[2]);
+    }
+    private Short4 pack_s4(short[] val) {
+        assert val.length == 4;
+        return new Short4(val[0], val[1], val[2], val[3]);
+    }
+    private Int2 pack_i2(int[] val) {
+        assert val.length == 2;
+        return new Int2(val[0], val[1]);
+    }
+    private Int3 pack_i3(int[] val) {
+        assert val.length == 3;
+        return new Int3(val[0], val[1], val[2]);
+    }
+    private Int4 pack_i4(int[] val) {
+        assert val.length == 4;
+        return new Int4(val[0], val[1], val[2], val[3]);
+    }
+    private Long2 pack_l2(long[] val) {
+        assert val.length == 2;
+        return new Long2(val[0], val[1]);
+    }
+    private Long3 pack_l3(long[] val) {
+        assert val.length == 3;
+        return new Long3(val[0], val[1], val[2]);
+    }
+    private Long4 pack_l4(long[] val) {
+        assert val.length == 4;
+        return new Long4(val[0], val[1], val[2], val[3]);
+    }
+
+    // random vector generation functions
+    private float[] randvec_float(int dim) {
+        float[] fv = new float[dim];
+        for (int i = 0; i < dim; ++i)
+            fv[i] = rand.nextFloat();
+        return fv;
+    }
+    private byte[] randvec_char(int dim) {
+        byte[] cv = new byte[dim];
+        rand.nextBytes(cv);
+        return cv;
+    }
+    private short[] randvec_uchar(int dim) {
+       short[] ucv = new short[dim];
+       for (int i = 0; i < dim; ++i)
+           ucv[i] = (short)rand.nextInt(0x1 << 8);
+       return ucv;
+    }
+    private short[] randvec_short(int dim) {
+        short[] sv = new short[dim];
+        for (int i = 0; i < dim; ++i)
+            sv[i] = (short)rand.nextInt(0x1 << 16);
+        return sv;
+    }
+    private int[] randvec_ushort(int dim) {
+        int[] usv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            usv[i] = rand.nextInt(0x1 << 16);
+        return usv;
+    }
+    private int[] randvec_int(int dim) {
+        int[] iv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            iv[i] = rand.nextInt();
+        return iv;
+    }
+    private long[] randvec_uint(int dim) {
+        long[] uiv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        return uiv;
+    }
+    private long[] randvec_long(int dim) {
+        long[] lv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            lv[i] = rand.nextLong();
+        return lv;
+    }
+    // TODO:  unsigned long generator
+
+    // min reference functions
+    private float min(float v1, float v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private float[] min(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private short min(short v1, short v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private short[] min(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private int min(int v1, int v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private int[] min(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private long min(long v1, long v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private long[] min(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of min
+
+    // max reference functions
+    private float max(float v1, float v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private float[] max(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private byte max(byte v1, byte v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private byte[] max(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private short max(short v1, short v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private short[] max(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private int max(int v1, int v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private int[] max(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private long max(long v1, long v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private long[] max(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of max
+
+    // fmin reference functions
+    private float fmin(float v1, float v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float[] v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2);
+        return rv;
+    }
+
+    // fmax reference functions
+    private float fmax(float v1, float v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float[] v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_math_agree s) {
+        float x = rand.nextFloat();
+        float y = rand.nextFloat();
+
+        s.set_x(x);
+        s.set_y(y);
+        s.set_result_add(x + y);
+        s.set_result_sub(x - y);
+        s.set_result_mul(x * y);
+        s.set_result_div(x / y);
+
+        // Generate random vectors of all types
+        float rand_f1_0 = rand.nextFloat();
+        float[] rand_f2_0 = randvec_float(2);
+        float[] rand_f3_0 = randvec_float(3);
+        float[] rand_f4_0 = randvec_float(4);
+        float rand_f1_1 = rand.nextFloat();
+        float[] rand_f2_1 = randvec_float(2);
+        float[] rand_f3_1 = randvec_float(3);
+        float[] rand_f4_1 = randvec_float(4);
+        short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_0 = randvec_uchar(2);
+        short[] rand_uc3_0 = randvec_uchar(3);
+        short[] rand_uc4_0 = randvec_uchar(4);
+        short rand_uc1_1 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_1 = randvec_uchar(2);
+        short[] rand_uc3_1 = randvec_uchar(3);
+        short[] rand_uc4_1 = randvec_uchar(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
+        int rand_us1_0 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_0 = randvec_ushort(2);
+        int[] rand_us3_0 = randvec_ushort(3);
+        int[] rand_us4_0 = randvec_ushort(4);
+        int rand_us1_1 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_1 = randvec_ushort(2);
+        int[] rand_us3_1 = randvec_ushort(3);
+        int[] rand_us4_1 = randvec_ushort(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
+        long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_0 = randvec_uint(2);
+        long[] rand_ui3_0 = randvec_uint(3);
+        long[] rand_ui4_0 = randvec_uint(4);
+        long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_1 = randvec_uint(2);
+        long[] rand_ui3_1 = randvec_uint(3);
+        long[] rand_ui4_1 = randvec_uint(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
+        // TODO:  generate unsigned long vectors
+
+        // Set random vectors in renderscript code
+        s.set_rand_f1_0(rand_f1_0);
+        s.set_rand_f2_0(pack_f2(rand_f2_0));
+        s.set_rand_f3_0(pack_f3(rand_f3_0));
+        s.set_rand_f4_0(pack_f4(rand_f4_0));
+        s.set_rand_f1_1(rand_f1_1);
+        s.set_rand_f2_1(pack_f2(rand_f2_1));
+        s.set_rand_f3_1(pack_f3(rand_f3_1));
+        s.set_rand_f4_1(pack_f4(rand_f4_1));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_ss1_0(rand_ss1_0);
+        s.set_rand_ss2_0(pack_s2(rand_ss2_0));
+        s.set_rand_ss3_0(pack_s3(rand_ss3_0));
+        s.set_rand_ss4_0(pack_s4(rand_ss4_0));
+        s.set_rand_ss1_1(rand_ss1_1);
+        s.set_rand_ss2_1(pack_s2(rand_ss2_1));
+        s.set_rand_ss3_1(pack_s3(rand_ss3_1));
+        s.set_rand_ss4_1(pack_s4(rand_ss4_1));
+        s.set_rand_us1_0(rand_us1_0);
+        s.set_rand_us2_0(pack_i2(rand_us2_0));
+        s.set_rand_us3_0(pack_i3(rand_us3_0));
+        s.set_rand_us4_0(pack_i4(rand_us4_0));
+        s.set_rand_us1_1(rand_us1_1);
+        s.set_rand_us2_1(pack_i2(rand_us2_1));
+        s.set_rand_us3_1(pack_i3(rand_us3_1));
+        s.set_rand_us4_1(pack_i4(rand_us4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
+        s.set_rand_ui1_0(rand_ui1_0);
+        s.set_rand_ui2_0(pack_l2(rand_ui2_0));
+        s.set_rand_ui3_0(pack_l3(rand_ui3_0));
+        s.set_rand_ui4_0(pack_l4(rand_ui4_0));
+        s.set_rand_ui1_1(rand_ui1_1);
+        s.set_rand_ui2_1(pack_l2(rand_ui2_1));
+        s.set_rand_ui3_1(pack_l3(rand_ui3_1));
+        s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        // TODO:  set unsigned long vectors
+
+        // Set results for min
+        s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1));
+        s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
+        s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
+        s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s2(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
+        s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
+        s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
+        s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
+        s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
+        s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
+        s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
+        s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
+        s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
+        s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
+        s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
+        s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
+        s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
+        s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
+        s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
+        // TODO:  set results for unsigned long min
+
+        // Set results for max
+        s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1));
+        s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
+        s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
+        s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s2(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
+        s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
+        s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
+        s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
+        s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
+        s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
+        s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
+        s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
+        s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
+        s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
+        s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
+        s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
+        s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
+        s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
+        s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
+        s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
+        s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
+
+        // TODO:  set results for unsigned long max
+
+        // Set results for fmin
+        s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1));
+        s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1)));
+        s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1)));
+        s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1)));
+        s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1)));
+        s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1)));
+        s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1)));
+
+        // Set results for fmax
+        s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1));
+        s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1)));
+        s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1)));
+        s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1)));
+        s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1)));
+        s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1)));
+        s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1)));
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_agree s = new ScriptC_math_agree(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_math_agree_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_math_conformance.java b/java/tests/RsTest/src/com/android/rs/test/UT_math_conformance.java
new file mode 100644
index 0000000..620eeb5
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_math_conformance.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_math_conformance extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math_conformance(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Conformance", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_conformance s =
+                new ScriptC_math_conformance(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_conformance_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_mesh.java b/java/tests/RsTest/src/com/android/rs/test/UT_mesh.java
new file mode 100644
index 0000000..29e5025
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_mesh.java
@@ -0,0 +1,75 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Mesh.*;
+
+public class UT_mesh extends UnitTest {
+    private Resources mRes;
+
+    Mesh mesh;
+
+    protected UT_mesh(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Mesh", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_mesh s) {
+        Allocation vAlloc0 = Allocation.createSized(RS, Element.F32(RS), 10);
+        Allocation vAlloc1 = Allocation.createSized(RS, Element.F32_2(RS), 10);
+
+        Allocation iAlloc0 = Allocation.createSized(RS, Element.I16(RS), 10);
+        Allocation iAlloc2 = Allocation.createSized(RS, Element.I16(RS), 10);
+
+        Mesh.AllocationBuilder mBuilder = new Mesh.AllocationBuilder(RS);
+        mBuilder.addVertexAllocation(vAlloc0);
+        mBuilder.addVertexAllocation(vAlloc1);
+
+        mBuilder.addIndexSetAllocation(iAlloc0, Primitive.POINT);
+        mBuilder.addIndexSetType(Primitive.LINE);
+        mBuilder.addIndexSetAllocation(iAlloc2, Primitive.TRIANGLE);
+
+        s.set_mesh(mBuilder.create());
+        s.set_vertexAlloc0(vAlloc0);
+        s.set_vertexAlloc1(vAlloc1);
+        s.set_indexAlloc0(iAlloc0);
+        s.set_indexAlloc2(iAlloc2);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_mesh s = new ScriptC_mesh(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_mesh_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_min.java b/java/tests/RsTest/src/com/android/rs/test/UT_min.java
new file mode 100644
index 0000000..137cae9
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_min.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_min extends UnitTest {
+    private Resources mRes;
+
+    protected UT_min(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Min (relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_min s = new ScriptC_min(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_min_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_noroot.java b/java/tests/RsTest/src/com/android/rs/test/UT_noroot.java
new file mode 100644
index 0000000..69526a8
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_noroot.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_noroot extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_noroot(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (no root)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_noroot s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_noroot s = new ScriptC_noroot(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_noroot_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_primitives.java b/java/tests/RsTest/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..c1234f0
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,103 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+    private Resources mRes;
+
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_primitives s) {
+        float pF = s.get_floatTest();
+        if (pF != 1.99f) {
+            return false;
+        }
+        s.set_floatTest(2.99f);
+
+        double pD = s.get_doubleTest();
+        if (pD != 2.05) {
+            return false;
+        }
+        s.set_doubleTest(3.05);
+
+        byte pC = s.get_charTest();
+        if (pC != -8) {
+            return false;
+        }
+        s.set_charTest((byte)-16);
+
+        short pS = s.get_shortTest();
+        if (pS != -16) {
+            return false;
+        }
+        s.set_shortTest((short)-32);
+
+        int pI = s.get_intTest();
+        if (pI != -32) {
+            return false;
+        }
+        s.set_intTest(-64);
+
+        long pL = s.get_longTest();
+        if (pL != 17179869184l) {
+            return false;
+        }
+        s.set_longTest(17179869185l);
+
+        long puL = s.get_ulongTest();
+        if (puL != 4611686018427387904L) {
+            return false;
+        }
+        s.set_ulongTest(4611686018427387903L);
+
+
+        long pLL = s.get_longlongTest();
+        if (pLL != 68719476736L) {
+            return false;
+        }
+        s.set_longlongTest(68719476735L);
+
+        long pu64 = s.get_uint64_tTest();
+        if (pu64 != 117179869184l) {
+            return false;
+        }
+        s.set_uint64_tTest(117179869185l);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_primitives s = new ScriptC_primitives(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_primitives_test(0, 0);
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_program_raster.java b/java/tests/RsTest/src/com/android/rs/test/UT_program_raster.java
new file mode 100644
index 0000000..046a215
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_program_raster.java
@@ -0,0 +1,81 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramRaster;
+import android.renderscript.ProgramRaster.CullMode;
+
+public class UT_program_raster extends UnitTest {
+    private Resources mRes;
+
+    ProgramRaster pointSpriteEnabled;
+    ProgramRaster cullMode;
+
+    protected UT_program_raster(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ProgramRaster", ctx);
+        mRes = res;
+    }
+
+    private ProgramRaster.Builder getDefaultBuilder(RenderScript RS) {
+        ProgramRaster.Builder b = new ProgramRaster.Builder(RS);
+        b.setCullMode(CullMode.BACK);
+        b.setPointSpriteEnabled(false);
+        return b;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_program_raster s) {
+        ProgramRaster.Builder b = getDefaultBuilder(RS);
+        pointSpriteEnabled = b.setPointSpriteEnabled(true).create();
+        b = getDefaultBuilder(RS);
+        cullMode = b.setCullMode(CullMode.FRONT).create();
+
+        s.set_pointSpriteEnabled(pointSpriteEnabled);
+        s.set_cullMode(cullMode);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_program_raster s = new ScriptC_program_raster(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_program_raster_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+        _RS_ASSERT("pointSpriteEnabled.isPointSpriteEnabled() == true",
+                    pointSpriteEnabled.isPointSpriteEnabled() == true);
+        _RS_ASSERT("pointSpriteEnabled.getCullMode() == ProgramRaster.CullMode.BACK",
+                    pointSpriteEnabled.getCullMode() == ProgramRaster.CullMode.BACK);
+
+        _RS_ASSERT("cullMode.isPointSpriteEnabled() == false",
+                    cullMode.isPointSpriteEnabled() == false);
+        _RS_ASSERT("cullMode.getCullMode() == ProgramRaster.CullMode.FRONT",
+                    cullMode.getCullMode() == ProgramRaster.CullMode.FRONT);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_program_store.java b/java/tests/RsTest/src/com/android/rs/test/UT_program_store.java
new file mode 100644
index 0000000..6510b6b
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_program_store.java
@@ -0,0 +1,175 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramStore.Builder;
+import android.renderscript.ProgramStore.DepthFunc;
+
+public class UT_program_store extends UnitTest {
+    private Resources mRes;
+
+    ProgramStore ditherEnable;
+    ProgramStore colorRWriteEnable;
+    ProgramStore colorGWriteEnable;
+    ProgramStore colorBWriteEnable;
+    ProgramStore colorAWriteEnable;
+    ProgramStore blendSrc;
+    ProgramStore blendDst;
+    ProgramStore depthWriteEnable;
+    ProgramStore depthFunc;
+
+    protected UT_program_store(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ProgramStore", ctx);
+        mRes = res;
+    }
+
+    private ProgramStore.Builder getDefaultBuilder(RenderScript RS) {
+        ProgramStore.Builder b = new ProgramStore.Builder(RS);
+        b.setBlendFunc(ProgramStore.BlendSrcFunc.ZERO, ProgramStore.BlendDstFunc.ZERO);
+        b.setColorMaskEnabled(false, false, false, false);
+        b.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+        b.setDepthMaskEnabled(false);
+        b.setDitherEnabled(false);
+        return b;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_program_store s) {
+        ProgramStore.Builder b = getDefaultBuilder(RS);
+        ditherEnable = b.setDitherEnabled(true).create();
+
+        b = getDefaultBuilder(RS);
+        colorRWriteEnable = b.setColorMaskEnabled(true,  false, false, false).create();
+
+        b = getDefaultBuilder(RS);
+        colorGWriteEnable = b.setColorMaskEnabled(false, true,  false, false).create();
+
+        b = getDefaultBuilder(RS);
+        colorBWriteEnable = b.setColorMaskEnabled(false, false, true,  false).create();
+
+        b = getDefaultBuilder(RS);
+        colorAWriteEnable = b.setColorMaskEnabled(false, false, false, true).create();
+
+        b = getDefaultBuilder(RS);
+        blendSrc = b.setBlendFunc(ProgramStore.BlendSrcFunc.DST_COLOR,
+                                  ProgramStore.BlendDstFunc.ZERO).create();
+
+        b = getDefaultBuilder(RS);
+        blendDst = b.setBlendFunc(ProgramStore.BlendSrcFunc.ZERO,
+                                  ProgramStore.BlendDstFunc.DST_ALPHA).create();
+
+        b = getDefaultBuilder(RS);
+        depthWriteEnable = b.setDepthMaskEnabled(true).create();
+
+        b = getDefaultBuilder(RS);
+        depthFunc = b.setDepthFunc(ProgramStore.DepthFunc.GREATER).create();
+
+        s.set_ditherEnable(ditherEnable);
+        s.set_colorRWriteEnable(colorRWriteEnable);
+        s.set_colorGWriteEnable(colorGWriteEnable);
+        s.set_colorBWriteEnable(colorBWriteEnable);
+        s.set_colorAWriteEnable(colorAWriteEnable);
+        s.set_blendSrc(blendSrc);
+        s.set_blendDst(blendDst);
+        s.set_depthWriteEnable(depthWriteEnable);
+        s.set_depthFunc(depthFunc);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_program_store s = new ScriptC_program_store(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_program_store_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    void checkObject(ProgramStore ps,
+                     boolean depthMask,
+                     DepthFunc df,
+                     BlendSrcFunc bsf,
+                     BlendDstFunc bdf,
+                     boolean R,
+                     boolean G,
+                     boolean B,
+                     boolean A,
+                     boolean dither) {
+        _RS_ASSERT("ps.isDepthMaskEnabled() == depthMask", ps.isDepthMaskEnabled() == depthMask);
+        _RS_ASSERT("ps.getDepthFunc() == df", ps.getDepthFunc() == df);
+        _RS_ASSERT("ps.getBlendSrcFunc() == bsf", ps.getBlendSrcFunc() == bsf);
+        _RS_ASSERT("ps.getBlendDstFunc() == bdf", ps.getBlendDstFunc() == bdf);
+        _RS_ASSERT("ps.isColorMaskRedEnabled() == R", ps.isColorMaskRedEnabled() == R);
+        _RS_ASSERT("ps.isColorMaskGreenEnabled() == G", ps.isColorMaskGreenEnabled() == G);
+        _RS_ASSERT("ps.isColorMaskBlueEnabled () == B", ps.isColorMaskBlueEnabled () == B);
+        _RS_ASSERT("ps.isColorMaskAlphaEnabled() == A", ps.isColorMaskAlphaEnabled() == A);
+        _RS_ASSERT("ps.isDitherEnabled() == dither", ps.isDitherEnabled() == dither);
+    }
+
+    void varyBuilderColorAndDither(ProgramStore.Builder pb,
+                                   boolean depthMask,
+                                   DepthFunc df,
+                                   BlendSrcFunc bsf,
+                                   BlendDstFunc bdf) {
+        for (int r = 0; r <= 1; r++) {
+            boolean isR = (r == 1);
+            for (int g = 0; g <= 1; g++) {
+                boolean isG = (g == 1);
+                for (int b = 0; b <= 1; b++) {
+                    boolean isB = (b == 1);
+                    for (int a = 0; a <= 1; a++) {
+                        boolean isA = (a == 1);
+                        for (int dither = 0; dither <= 1; dither++) {
+                            boolean isDither = (dither == 1);
+                            pb.setDitherEnabled(isDither);
+                            pb.setColorMaskEnabled(isR, isG, isB, isA);
+                            ProgramStore ps = pb.create();
+                            checkObject(ps, depthMask, df, bsf, bdf, isR, isG, isB, isA, isDither);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void testJavaSide(RenderScript RS) {
+        for (int depth = 0; depth <= 1; depth++) {
+            boolean depthMask = (depth == 1);
+            for (DepthFunc df : DepthFunc.values()) {
+                for (BlendSrcFunc bsf : BlendSrcFunc.values()) {
+                    for (BlendDstFunc bdf : BlendDstFunc.values()) {
+                        ProgramStore.Builder b = new ProgramStore.Builder(RS);
+                        b.setDepthFunc(df);
+                        b.setDepthMaskEnabled(depthMask);
+                        b.setBlendFunc(bsf, bdf);
+                        varyBuilderColorAndDither(b, depthMask, df, bsf, bdf);
+                    }
+                }
+            }
+        }
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testJavaSide(pRS);
+        testScriptSide(pRS);
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_refcount.java b/java/tests/RsTest/src/com/android/rs/test/UT_refcount.java
new file mode 100644
index 0000000..22bbd2f
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_refcount.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_refcount extends UnitTest {
+    private Resources mRes;
+
+    protected UT_refcount(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Refcount", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_refcount s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 500;
+        int Y = 700;
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_globalA(A);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        pRS.setMessageHandler(mRsMessage);
+        ScriptC_refcount s = new ScriptC_refcount(pRS);
+        initializeGlobals(pRS, s);
+        s.invoke_refcount_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_rsdebug.java b/java/tests/RsTest/src/com/android/rs/test/UT_rsdebug.java
new file mode 100644
index 0000000..548288b
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_rsdebug.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rsdebug extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rsdebug(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_rstime.java b/java/tests/RsTest/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..f000412
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.setTimeZone("America/Los_Angeles");
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_rstypes.java b/java/tests/RsTest/src/com/android/rs/test/UT_rstypes.java
new file mode 100644
index 0000000..f677f10
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_rstypes.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstypes extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstypes(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_sampler.java b/java/tests/RsTest/src/com/android/rs/test/UT_sampler.java
new file mode 100644
index 0000000..00c850c
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_sampler.java
@@ -0,0 +1,150 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Sampler;
+import android.renderscript.Sampler.Value;
+
+public class UT_sampler extends UnitTest {
+    private Resources mRes;
+
+    Sampler minification;
+    Sampler magnification;
+    Sampler wrapS;
+    Sampler wrapT;
+    Sampler anisotropy;
+
+    protected UT_sampler(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Sampler", ctx);
+        mRes = res;
+    }
+
+    private Sampler.Builder getDefaultBuilder(RenderScript RS) {
+        Sampler.Builder b = new Sampler.Builder(RS);
+        b.setMinification(Value.NEAREST);
+        b.setMagnification(Value.NEAREST);
+        b.setWrapS(Value.CLAMP);
+        b.setWrapT(Value.CLAMP);
+        b.setAnisotropy(1.0f);
+        return b;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_sampler s) {
+        Sampler.Builder b = getDefaultBuilder(RS);
+        b.setMinification(Value.LINEAR_MIP_LINEAR);
+        minification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setMagnification(Value.LINEAR);
+        magnification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapS(Value.WRAP);
+        wrapS = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapT(Value.WRAP);
+        wrapT = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setAnisotropy(8.0f);
+        anisotropy = b.create();
+
+        s.set_minification(minification);
+        s.set_magnification(magnification);
+        s.set_wrapS(wrapS);
+        s.set_wrapT(wrapT);
+        s.set_anisotropy(anisotropy);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_sampler s = new ScriptC_sampler(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_sampler_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+        _RS_ASSERT("minification.getMagnification() == Sampler.Value.NEAREST",
+                    minification.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR",
+                    minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR);
+        _RS_ASSERT("minification.getWrapS() == Sampler.Value.CLAMP",
+                    minification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getWrapT() == Sampler.Value.CLAMP",
+                    minification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getAnisotropy() == 1.0f",
+                    minification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("magnification.getMagnification() == Sampler.Value.LINEAR",
+                    magnification.getMagnification() == Sampler.Value.LINEAR);
+        _RS_ASSERT("magnification.getMinification() == Sampler.Value.NEAREST",
+                    magnification.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("magnification.getWrapS() == Sampler.Value.CLAMP",
+                    magnification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getWrapT() == Sampler.Value.CLAMP",
+                    magnification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getAnisotropy() == 1.0f",
+                    magnification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapS.getMagnification() == Sampler.Value.NEAREST",
+                    wrapS.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getMinification() == Sampler.Value.NEAREST",
+                    wrapS.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getWrapS() == Sampler.Value.WRAP",
+                    wrapS.getWrapS() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapS.getWrapT() == Sampler.Value.CLAMP",
+                    wrapS.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapS.getAnisotropy() == 1.0f",
+                    wrapS.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapT.getMagnification() == Sampler.Value.NEAREST",
+                    wrapT.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getMinification() == Sampler.Value.NEAREST",
+                    wrapT.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getWrapS() == Sampler.Value.CLAMP",
+                    wrapT.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapT.getWrapT() == Sampler.Value.WRAP",
+                    wrapT.getWrapT() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapT.getAnisotropy() == 1.0f",
+                    wrapT.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("anisotropy.getMagnification() == Sampler.Value.NEAREST",
+                    anisotropy.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getMinification() == Sampler.Value.NEAREST",
+                    anisotropy.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getWrapS() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getWrapT() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getAnisotropy() == 1.0f",
+                    anisotropy.getAnisotropy() == 8.0f);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_struct.java b/java/tests/RsTest/src/com/android/rs/test/UT_struct.java
new file mode 100644
index 0000000..6f47b72
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_struct.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_struct extends UnitTest {
+    private Resources mRes;
+
+    protected UT_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Struct", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_struct s = new ScriptC_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        ScriptField_Point2 p = new ScriptField_Point2(pRS, 1);
+        ScriptField_Point2.Item i = new ScriptField_Point2.Item();
+        int val = 100;
+        i.x = val;
+        i.y = val;
+        p.set(i, 0, true);
+        s.bind_point2(p);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+
+        val = 200;
+        p.set_x(0, val, true);
+        p.set_y(0, val, true);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_unsigned.java b/java/tests/RsTest/src/com/android/rs/test/UT_unsigned.java
new file mode 100644
index 0000000..9ea0f8a
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_unsigned.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_unsigned extends UnitTest {
+    private Resources mRes;
+
+    protected UT_unsigned(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Unsigned", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_unsigned s) {
+        short pUC = s.get_uc();
+        if (pUC != 5) {
+            return false;
+        }
+        s.set_uc((short)129);
+
+        long pUI = s.get_ui();
+        if (pUI != 37) {
+            return false;
+        }
+        s.set_ui(0x7fffffff);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_unsigned s = new ScriptC_unsigned(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_unsigned_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_vector.java b/java/tests/RsTest/src/com/android/rs/test/UT_vector.java
new file mode 100644
index 0000000..91cc0af
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UT_vector.java
@@ -0,0 +1,318 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_vector extends UnitTest {
+    private Resources mRes;
+
+    protected UT_vector(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Vector", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_vector s) {
+        Float2 F2 = s.get_f2();
+        if (F2.x != 1.0f || F2.y != 2.0f) {
+            return false;
+        }
+        F2.x = 2.99f;
+        F2.y = 3.99f;
+        s.set_f2(F2);
+
+        Float3 F3 = s.get_f3();
+        if (F3.x != 1.0f || F3.y != 2.0f || F3.z != 3.0f) {
+            return false;
+        }
+        F3.x = 2.99f;
+        F3.y = 3.99f;
+        F3.z = 4.99f;
+        s.set_f3(F3);
+
+        Float4 F4 = s.get_f4();
+        if (F4.x != 1.0f || F4.y != 2.0f || F4.z != 3.0f || F4.w != 4.0f) {
+            return false;
+        }
+        F4.x = 2.99f;
+        F4.y = 3.99f;
+        F4.z = 4.99f;
+        F4.w = 5.99f;
+        s.set_f4(F4);
+
+        Double2 D2 = s.get_d2();
+        if (D2.x != 1.0 || D2.y != 2.0) {
+            return false;
+        }
+        D2.x = 2.99;
+        D2.y = 3.99;
+        s.set_d2(D2);
+
+        Double3 D3 = s.get_d3();
+        if (D3.x != 1.0 || D3.y != 2.0 || D3.z != 3.0) {
+            return false;
+        }
+        D3.x = 2.99;
+        D3.y = 3.99;
+        D3.z = 4.99;
+        s.set_d3(D3);
+
+        Double4 D4 = s.get_d4();
+        if (D4.x != 1.0 || D4.y != 2.0 || D4.z != 3.0 || D4.w != 4.0) {
+            return false;
+        }
+        D4.x = 2.99;
+        D4.y = 3.99;
+        D4.z = 4.99;
+        D4.w = 5.99;
+        s.set_d4(D4);
+
+        Byte2 B2 = s.get_i8_2();
+        if (B2.x != 1 || B2.y != 2) {
+            return false;
+        }
+        B2.x = 2;
+        B2.y = 3;
+        s.set_i8_2(B2);
+
+        Byte3 B3 = s.get_i8_3();
+        if (B3.x != 1 || B3.y != 2 || B3.z != 3) {
+            return false;
+        }
+        B3.x = 2;
+        B3.y = 3;
+        B3.z = 4;
+        s.set_i8_3(B3);
+
+        Byte4 B4 = s.get_i8_4();
+        if (B4.x != 1 || B4.y != 2 || B4.z != 3 || B4.w != 4) {
+            return false;
+        }
+        B4.x = 2;
+        B4.y = 3;
+        B4.z = 4;
+        B4.w = 5;
+        s.set_i8_4(B4);
+
+        Short2 S2 = s.get_u8_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_u8_2(S2);
+
+        Short3 S3 = s.get_u8_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_u8_3(S3);
+
+        Short4 S4 = s.get_u8_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_u8_4(S4);
+
+        S2 = s.get_i16_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_i16_2(S2);
+
+        S3 = s.get_i16_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_i16_3(S3);
+
+        S4 = s.get_i16_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_i16_4(S4);
+
+        Int2 I2 = s.get_u16_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_u16_2(I2);
+
+        Int3 I3 = s.get_u16_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_u16_3(I3);
+
+        Int4 I4 = s.get_u16_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_u16_4(I4);
+
+        I2 = s.get_i32_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_i32_2(I2);
+
+        I3 = s.get_i32_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_i32_3(I3);
+
+        I4 = s.get_i32_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_i32_4(I4);
+
+        Long2 L2 = s.get_u32_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u32_2(L2);
+
+        Long3 L3 = s.get_u32_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u32_3(L3);
+
+        Long4 L4 = s.get_u32_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u32_4(L4);
+
+        L2 = s.get_i64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_i64_2(L2);
+
+        L3 = s.get_i64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_i64_3(L3);
+
+        L4 = s.get_i64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_i64_4(L4);
+
+        L2 = s.get_u64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u64_2(L2);
+
+        L3 = s.get_u64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u64_3(L3);
+
+        L4 = s.get_u64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u64_4(L4);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_vector s = new ScriptC_vector(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_vector_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/UnitTest.java b/java/tests/RsTest/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..fbac124
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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 com.android.rs.test;
+import android.content.Context;
+import android.util.Log;
+import android.renderscript.RenderScript.RSMessageHandler;
+
+public class UnitTest extends Thread {
+    public String name;
+    private int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
+    }
+
+    protected void _RS_ASSERT(String message, boolean b) {
+        if(b == false) {
+            Log.e(name, message + " FAILED");
+            failTest();
+        }
+    }
+
+    private void updateUI() {
+        if (mItem != null) {
+            mItem.result = result;
+            msgHandled = true;
+            try {
+                mRSTC.refreshTestResults();
+            }
+            catch (IllegalStateException e) {
+                /* Ignore the case where our message receiver has been
+                   disconnected. This happens when we leave the application
+                   before it finishes running all of the unit tests. */
+            }
+        }
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = 1;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = -1;
+                        break;
+                    default:
+                        RSTest.log("Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            updateUI();
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public int getResult() {
+        return result;
+    }
+
+    public void failTest() {
+        result = -1;
+        updateUI();
+    }
+
+    public void passTest() {
+        if (result != -1) {
+            result = 1;
+        }
+        updateUI();
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/alloc.rs b/java/tests/RsTest/src/com/android/rs/test/alloc.rs
new file mode 100644
index 0000000..1b5e2ac
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/alloc.rs
@@ -0,0 +1,92 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int dimZ;
+
+rs_allocation aRaw;
+rs_allocation aFaces;
+rs_allocation aLOD;
+rs_allocation aFacesLOD;
+
+void root(int *o, uint32_t x, uint32_t y) {
+    *o = x + y * dimX;
+}
+
+static bool test_alloc_dims() {
+    bool failed = false;
+    int i, j;
+
+    _RS_ASSERT(rsAllocationGetDimX(aRaw) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aRaw) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aRaw) == dimZ);
+
+    // Test 2D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(aRaw, i, j);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    // Test 1D addressing
+    for (i = 0; i < dimX; i++) {
+        rsDebug("Verifying ", i);
+        const void *p = rsGetElementAt(aRaw, i);
+        int val = *(const int *)p;
+        _RS_ASSERT(val == i);
+    }
+
+    // Test 3D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(aRaw, i, j, 0);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    _RS_ASSERT(rsAllocationGetDimX(aFaces) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFaces) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFaces) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFaces) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFaces) == 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aLOD) == 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aLOD) != 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aFacesLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFacesLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFacesLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFacesLOD) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFacesLOD) != 0);
+
+    if (failed) {
+        rsDebug("test_alloc_dims FAILED", 0);
+    }
+    else {
+        rsDebug("test_alloc_dims PASSED", 0);
+    }
+
+    return failed;
+}
+
+void alloc_test() {
+    bool failed = false;
+    failed |= test_alloc_dims();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/array_alloc.rs b/java/tests/RsTest/src/com/android/rs/test/array_alloc.rs
new file mode 100644
index 0000000..74ffdb1
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/array_alloc.rs
@@ -0,0 +1,21 @@
+#include "shared.rsh"
+
+const int dimX = 20;
+rs_allocation a[dimX];
+
+void array_alloc_test() {
+    bool failed = false;
+
+    for (int i = 0; i < dimX; i++) {
+        rsDebug("i: ", i);
+        _RS_ASSERT(rsAllocationGetDimX(a[i]) == 1);
+    }
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/array_init.rs b/java/tests/RsTest/src/com/android/rs/test/array_init.rs
new file mode 100644
index 0000000..842249a
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/array_init.rs
@@ -0,0 +1,58 @@
+#include "shared.rsh"
+
+// Testing constant array initialization
+float fa[4] = {1.0, 9.9999f};
+double da[2] = {7.0, 8.88888};
+char ca[4] = {'a', 7, 'b', 'c'};
+short sa[4] = {1, 1, 2, 3};
+int ia[4] = {5, 8};
+long la[2] = {13, 21};
+long long lla[4] = {34};
+bool ba[3] = {true, false};
+
+void array_init_test() {
+    bool failed = false;
+
+    _RS_ASSERT(fa[0] == 1.0);
+    _RS_ASSERT(fa[1] == 9.9999f);
+    _RS_ASSERT(fa[2] == 0);
+    _RS_ASSERT(fa[3] == 0);
+
+    _RS_ASSERT(da[0] == 7.0);
+    _RS_ASSERT(da[1] == 8.88888);
+
+    _RS_ASSERT(ca[0] == 'a');
+    _RS_ASSERT(ca[1] == 7);
+    _RS_ASSERT(ca[2] == 'b');
+    _RS_ASSERT(ca[3] == 'c');
+
+    _RS_ASSERT(sa[0] == 1);
+    _RS_ASSERT(sa[1] == 1);
+    _RS_ASSERT(sa[2] == 2);
+    _RS_ASSERT(sa[3] == 3);
+
+    _RS_ASSERT(ia[0] == 5);
+    _RS_ASSERT(ia[1] == 8);
+    _RS_ASSERT(ia[2] == 0);
+    _RS_ASSERT(ia[3] == 0);
+
+    _RS_ASSERT(la[0] == 13);
+    _RS_ASSERT(la[1] == 21);
+
+    _RS_ASSERT(lla[0] == 34);
+    _RS_ASSERT(lla[1] == 0);
+    _RS_ASSERT(lla[2] == 0);
+    _RS_ASSERT(lla[3] == 0);
+
+    _RS_ASSERT(ba[0] == true);
+    _RS_ASSERT(ba[1] == false);
+    _RS_ASSERT(ba[2] == false);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/atomic.rs b/java/tests/RsTest/src/com/android/rs/test/atomic.rs
new file mode 100644
index 0000000..f0a5041
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/atomic.rs
@@ -0,0 +1,77 @@
+#include "shared.rsh"
+
+// Testing atomic operations
+static bool testUMax(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst > src ? dst : src);
+    uint32_t ret = rsAtomicMax(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUMin(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst < src ? dst : src);
+    uint32_t ret = rsAtomicMin(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUCas(uint32_t dst, uint32_t cmp, uint32_t swp) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst == cmp ? swp : dst);
+    uint32_t ret = rsAtomicCas(&dst, cmp, swp);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool test_atomics() {
+    bool failed = false;
+
+    failed |= testUMax(5, 6);
+    failed |= testUMax(6, 5);
+    failed |= testUMax(5, 0xf0000006);
+    failed |= testUMax(0xf0000006, 5);
+
+    failed |= testUMin(5, 6);
+    failed |= testUMin(6, 5);
+    failed |= testUMin(5, 0xf0000006);
+    failed |= testUMin(0xf0000006, 5);
+
+    failed |= testUCas(4, 4, 5);
+    failed |= testUCas(4, 5, 5);
+    failed |= testUCas(5, 5, 4);
+    failed |= testUCas(5, 4, 4);
+    failed |= testUCas(0xf0000004, 0xf0000004, 0xf0000005);
+    failed |= testUCas(0xf0000004, 0xf0000005, 0xf0000005);
+    failed |= testUCas(0xf0000005, 0xf0000005, 0xf0000004);
+    failed |= testUCas(0xf0000005, 0xf0000004, 0xf0000004);
+
+    if (failed) {
+        rsDebug("test_atomics FAILED", 0);
+    }
+    else {
+        rsDebug("test_atomics PASSED", 0);
+    }
+
+    return failed;
+}
+
+void atomic_test() {
+    bool failed = false;
+    failed |= test_atomics();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/bug_char.rs b/java/tests/RsTest/src/com/android/rs/test/bug_char.rs
new file mode 100644
index 0000000..dcd7b72
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/bug_char.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+char rand_sc1_0, rand_sc1_1;
+char2 rand_sc2_0, rand_sc2_1;
+
+char min_rand_sc1_sc1;
+char2 min_rand_sc2_sc2;
+
+static bool test_bug_char() {
+    bool failed = false;
+
+    rsDebug("rand_sc2_0.x: ", rand_sc2_0.x);
+    rsDebug("rand_sc2_0.y: ", rand_sc2_0.y);
+    rsDebug("rand_sc2_1.x: ", rand_sc2_1.x);
+    rsDebug("rand_sc2_1.y: ", rand_sc2_1.y);
+    char temp_sc1;
+    char2 temp_sc2;
+
+    temp_sc1 = min( rand_sc1_0, rand_sc1_1 );
+    if (temp_sc1 != min_rand_sc1_sc1) {
+        rsDebug("temp_sc1", temp_sc1);
+        failed = true;
+    }
+    rsDebug("broken", 'y');
+
+    temp_sc2 = min( rand_sc2_0, rand_sc2_1 );
+    if (temp_sc2.x != min_rand_sc2_sc2.x
+            || temp_sc2.y != min_rand_sc2_sc2.y) {
+        failed = true;
+    }
+
+
+    return failed;
+}
+
+void bug_char_test() {
+    bool failed = false;
+    failed |= test_bug_char();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/clamp.rs b/java/tests/RsTest/src/com/android/rs/test/clamp.rs
new file mode 100644
index 0000000..28b00bd
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/clamp.rs
@@ -0,0 +1,56 @@
+#include "shared.rsh"
+
+static bool test_clamp_vector() {
+    bool failed = false;
+
+    float2 src2 = { 2.0f, 2.0f};
+    float2 min2 = { 0.5f, -3.0f};
+    float2 max2 = { 1.0f, 9.0f};
+
+    float2 res2 = clamp(src2, min2, max2);
+    _RS_ASSERT(res2.x == 1.0f);
+    _RS_ASSERT(res2.y == 2.0f);
+
+
+    float3 src3 = { 2.0f, 2.0f, 1.0f};
+    float3 min3 = { 0.5f, -3.0f, 3.0f};
+    float3 max3 = { 1.0f, 9.0f, 4.0f};
+
+    float3 res3 = clamp(src3, min3, max3);
+    _RS_ASSERT(res3.x == 1.0f);
+    _RS_ASSERT(res3.y == 2.0f);
+    _RS_ASSERT(res3.z == 3.0f);
+
+
+    float4 src4 = { 2.0f, 2.0f, 1.0f, 4.0f };
+    float4 min4 = { 0.5f, -3.0f, 3.0f, 4.0f };
+    float4 max4 = { 1.0f, 9.0f, 4.0f, 4.0f };
+
+    float4 res4 = clamp(src4, min4, max4);
+    _RS_ASSERT(res4.x == 1.0f);
+    _RS_ASSERT(res4.y == 2.0f);
+    _RS_ASSERT(res4.z == 3.0f);
+    _RS_ASSERT(res4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_clamp_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_clamp_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void clamp_test() {
+    bool failed = false;
+    failed |= test_clamp_vector();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/clamp_relaxed.rs b/java/tests/RsTest/src/com/android/rs/test/clamp_relaxed.rs
new file mode 100644
index 0000000..71c65ae
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/clamp_relaxed.rs
@@ -0,0 +1,2 @@
+#include "clamp.rs"
+#pragma rs_fp_relaxed
diff --git a/java/tests/RsTest/src/com/android/rs/test/constant.rs b/java/tests/RsTest/src/com/android/rs/test/constant.rs
new file mode 100644
index 0000000..732eaef
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/constant.rs
@@ -0,0 +1,19 @@
+#include "shared.rsh"
+
+const float floatTest = 1.99f;
+const double doubleTest = 2.05;
+const char charTest = -8;
+const short shortTest = -16;
+const int intTest = -32;
+const long longTest = 17179869184l; // 1 << 34
+const long long longlongTest = 68719476736l; // 1 << 36
+
+const uchar ucharTest = 8;
+const ushort ushortTest = 16;
+const uint uintTest = 32;
+const ulong ulongTest = 4611686018427387904L;
+const int64_t int64_tTest = -17179869184l; // - 1 << 34
+const uint64_t uint64_tTest = 117179869184l;
+
+const bool boolTest = true;
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/convert.rs b/java/tests/RsTest/src/com/android/rs/test/convert.rs
new file mode 100644
index 0000000..e314f2b
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/convert.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+float4 f4 = { 2.0f, 4.0f, 6.0f, 8.0f };
+
+char4 i8_4 = { -1, -2, -3, 4 };
+
+static bool test_convert() {
+    bool failed = false;
+
+    f4 = convert_float4(i8_4);
+    _RS_ASSERT(f4.x == -1.0f);
+    _RS_ASSERT(f4.y == -2.0f);
+    _RS_ASSERT(f4.z == -3.0f);
+    _RS_ASSERT(f4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void convert_test() {
+    bool failed = false;
+    failed |= test_convert();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/convert_relaxed.rs b/java/tests/RsTest/src/com/android/rs/test/convert_relaxed.rs
new file mode 100644
index 0000000..81abb9b
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/convert_relaxed.rs
@@ -0,0 +1,2 @@
+#include "convert.rs"
+#pragma rs_fp_relaxed
diff --git a/java/tests/RsTest/src/com/android/rs/test/copy_test.rs b/java/tests/RsTest/src/com/android/rs/test/copy_test.rs
new file mode 100644
index 0000000..f4243eb
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/copy_test.rs
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "shared.rsh"
+
+void sendResult(bool pass) {
+    if (pass) {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+}
+
+
+float2 __attribute((kernel)) copyFloat2(float2 i) {
+    return i;
+}
+
+float3 __attribute((kernel)) copyFloat3(float3 i) {
+    return i;
+}
+
+float4 __attribute((kernel)) copyFloat4(float4 i) {
+    return i;
+}
+
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/element.rs b/java/tests/RsTest/src/com/android/rs/test/element.rs
new file mode 100644
index 0000000..419ce07
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/element.rs
@@ -0,0 +1,158 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element simpleElem;
+rs_element complexElem;
+typedef struct ComplexStruct {
+    float subElem0;
+    float subElem1;
+    int subElem2;
+    float arrayElem0[2];
+    int arrayElem1[5];
+    char subElem3;
+    float subElem4;
+    float2 subElem5;
+    float3 subElem6;
+    float4 subElem_7;
+} ComplexStruct_t;
+
+ComplexStruct_t *complexStruct;
+
+static const char *subElemNames[] = {
+    "subElem0",
+    "subElem1",
+    "subElem2",
+    "arrayElem0",
+    "arrayElem1",
+    "subElem3",
+    "subElem4",
+    "subElem5",
+    "subElem6",
+    "subElem_7",
+};
+
+static uint32_t subElemNamesSizes[] = {
+    8,
+    8,
+    8,
+    10,
+    10,
+    8,
+    8,
+    8,
+    8,
+    9,
+};
+
+static uint32_t subElemArraySizes[] = {
+    1,
+    1,
+    1,
+    2,
+    5,
+    1,
+    1,
+    1,
+    1,
+    1,
+};
+
+static void resetStruct() {
+    uint8_t *bytePtr = (uint8_t*)complexStruct;
+    uint32_t sizeOfStruct = sizeof(*complexStruct);
+    for(uint32_t i = 0; i < sizeOfStruct; i ++) {
+        bytePtr[i] = 0;
+    }
+}
+
+static bool equals(const char *name0, const char * name1, uint32_t len) {
+    for (uint32_t i = 0; i < len; i ++) {
+        if (name0[i] != name1[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool test_element_getters() {
+    bool failed = false;
+
+    uint32_t subElemOffsets[10];
+    uint32_t index = 0;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem0   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem1   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem2   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem0 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem1 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem3   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem4   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem5   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem6   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem_7  - (uint32_t)complexStruct;
+
+    uint32_t subElemCount = rsElementGetSubElementCount(simpleElem);
+    _RS_ASSERT(subElemCount == 0);
+    _RS_ASSERT(rsElementGetDataKind(simpleElem) == RS_KIND_USER);
+    _RS_ASSERT(rsElementGetDataType(simpleElem) == RS_TYPE_FLOAT_32);
+    _RS_ASSERT(rsElementGetVectorSize(simpleElem) == 3);
+
+    subElemCount = rsElementGetSubElementCount(complexElem);
+    _RS_ASSERT(subElemCount == 10);
+    _RS_ASSERT(rsElementGetDataKind(complexElem) == RS_KIND_USER);
+    _RS_ASSERT(rsElementGetDataType(complexElem) == RS_TYPE_NONE);
+    _RS_ASSERT(rsElementGetVectorSize(complexElem) == 1);
+    _RS_ASSERT(rsElementGetBytesSize(complexElem) == sizeof(*complexStruct));
+
+    char buffer[64];
+    for (uint32_t i = 0; i < subElemCount; i ++) {
+        rs_element subElem = rsElementGetSubElement(complexElem, i);
+        _RS_ASSERT(rsIsObject(subElem));
+
+        _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, i) == subElemNamesSizes[i] + 1);
+
+        uint32_t written = rsElementGetSubElementName(complexElem, i, buffer, 64);
+        _RS_ASSERT(written == subElemNamesSizes[i]);
+        _RS_ASSERT(equals(buffer, subElemNames[i], written));
+
+        _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, i) == subElemArraySizes[i]);
+        _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, i) == subElemOffsets[i]);
+    }
+
+    // Tests error checking
+    rs_element subElem = rsElementGetSubElement(complexElem, subElemCount);
+    _RS_ASSERT(!rsIsObject(subElem));
+
+    _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, subElemCount) == 0);
+
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, subElemCount, buffer, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, NULL, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, buffer, 0) == 0);
+    uint32_t written = rsElementGetSubElementName(complexElem, 0, buffer, 5);
+    _RS_ASSERT(written == 4);
+    _RS_ASSERT(buffer[4] == '\0');
+
+    _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, subElemCount) == 0);
+    _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, subElemCount) == 0);
+
+    if (failed) {
+        rsDebug("test_element_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_element_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void element_test() {
+    bool failed = false;
+    failed |= test_element_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/foreach.rs b/java/tests/RsTest/src/com/android/rs/test/foreach.rs
new file mode 100644
index 0000000..08e6bed
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/foreach.rs
@@ -0,0 +1,76 @@
+#include "shared.rsh"
+
+rs_allocation aRaw;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    _RS_ASSERT(*in == (x + y * dimX));
+    *out = 99 + x + y * dimX;
+    _RS_ASSERT(*out == (99 + x + y * dimX));
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void foreach_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/foreach_bounds.rs b/java/tests/RsTest/src/com/android/rs/test/foreach_bounds.rs
new file mode 100644
index 0000000..fa76390
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/foreach_bounds.rs
@@ -0,0 +1,62 @@
+#include "shared.rsh"
+
+int dimX;
+int dimY;
+int xStart = 0;
+int xEnd = 0;
+int yStart = 0;
+int yEnd = 0;
+
+static bool failed = false;
+
+rs_script s;
+rs_allocation aRaw;
+rs_allocation ain;
+rs_allocation aout;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+int __attribute__((kernel)) zero() {
+    return 0;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            if (i < xStart || i >= xEnd || j < yStart || j >= yEnd) {
+                _RS_ASSERT(v == 0);
+            } else {
+                _RS_ASSERT(v == (i + j * dimX));
+            }
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void foreach_bounds_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/fp_mad.rs b/java/tests/RsTest/src/com/android/rs/test/fp_mad.rs
new file mode 100644
index 0000000..b6f2b2a
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/fp_mad.rs
@@ -0,0 +1,174 @@
+#include "shared.rsh"
+
+const int TEST_COUNT = 1;
+
+static float data_f1[1025];
+static float4 data_f4[1025];
+
+static void test_mad4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 80); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = (data_f4[i] * 0.02f +
+                          data_f4[i+1] * 0.04f +
+                          data_f4[i+2] * 0.05f +
+                          data_f4[i+3] * 0.1f +
+                          data_f4[i+4] * 0.2f +
+                          data_f4[i+5] * 0.2f +
+                          data_f4[i+6] * 0.1f +
+                          data_f4[i+7] * 0.05f +
+                          data_f4[i+8] * 0.04f +
+                          data_f4[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad4 M ops", 1000.f / time);
+}
+
+static void test_mad(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 20); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = (data_f1[i] * 0.02f +
+                          data_f1[i+1] * 0.04f +
+                          data_f1[i+2] * 0.05f +
+                          data_f1[i+3] * 0.1f +
+                          data_f1[i+4] * 0.2f +
+                          data_f1[i+5] * 0.2f +
+                          data_f1[i+6] * 0.1f +
+                          data_f1[i+7] * 0.05f +
+                          data_f1[i+8] * 0.04f +
+                          data_f1[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad M ops", 1000.f / time);
+}
+
+static void test_norm(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = normalize(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_norm M ops", 10.f / time);
+}
+
+static void test_sincos4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10 / 4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos4 M ops", 10.f / time);
+}
+
+static void test_sincos(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos M ops", 10.f / time);
+}
+
+static void test_clamp(uint32_t index) {
+    start();
+
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = clamp(data_f1[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp M ops", 100.f / time);
+
+    start();
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            if (data_f1[i] < -1.f) data_f1[i] = -1.f;
+            if (data_f1[i] > -1.f) data_f1[i] = 1.f;
+        }
+    }
+
+    time = end(index);
+    rsDebug("fp_clamp ref M ops", 100.f / time);
+}
+
+static void test_clamp4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100 /4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = clamp(data_f4[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp4 M ops", 100.f / time);
+}
+
+void fp_mad_test(uint32_t index, int test_num) {
+    int x;
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f;
+        data_f4[x].x = (x & 0xf) * 0.1f;
+        data_f4[x].y = (x & 0xf0) * 0.1f;
+        data_f4[x].z = (x & 0x33) * 0.1f;
+        data_f4[x].w = (x & 0x77) * 0.1f;
+    }
+
+    test_mad4(index);
+    test_mad(index);
+
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].x = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].y = (x & 0xf0) * 0.1f + 1.f;
+        data_f4[x].z = (x & 0x33) * 0.1f + 1.f;
+        data_f4[x].w = (x & 0x77) * 0.1f + 1.f;
+    }
+
+    test_norm(index);
+    test_sincos4(index);
+    test_sincos(index);
+    test_clamp4(index);
+    test_clamp(index);
+
+    // TODO Actually verify test result accuracy
+    rsDebug("fp_mad_test PASSED", 0);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/int4.rs b/java/tests/RsTest/src/com/android/rs/test/int4.rs
new file mode 100644
index 0000000..c791cab
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/int4.rs
@@ -0,0 +1,29 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+uchar4 u4 = 4;
+int4 gi4 = {2, 2, 2, 2};
+
+void int4_test() {
+    bool failed = false;
+    int4 i4 = {u4.x, u4.y, u4.z, u4.w};
+    i4 *= gi4;
+
+    rsDebug("i4.x", i4.x);
+    rsDebug("i4.y", i4.y);
+    rsDebug("i4.z", i4.z);
+    rsDebug("i4.w", i4.w);
+
+    _RS_ASSERT(i4.x == 8);
+    _RS_ASSERT(i4.y == 8);
+    _RS_ASSERT(i4.z == 8);
+    _RS_ASSERT(i4.w == 8);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/kernel.rs b/java/tests/RsTest/src/com/android/rs/test/kernel.rs
new file mode 100644
index 0000000..d6c9df3
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/kernel.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+int *ain;
+int *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(int *out) {
+    *out = 7;
+}
+
+
+int __attribute__((kernel)) root(int ain, uint32_t x) {
+    _RS_ASSERT(ain == 7);
+    return ain + x;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i] == (i + ain[i]));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/kernel_struct.rs b/java/tests/RsTest/src/com/android/rs/test/kernel_struct.rs
new file mode 100644
index 0000000..62c30ae
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/kernel_struct.rs
@@ -0,0 +1,66 @@
+#include "shared.rsh"
+
+struct simpleStruct {
+    int i1;
+    char ignored1;
+    float f1;
+    int i2;
+    char ignored2;
+    float f2;
+};
+
+struct simpleStruct *ain;
+struct simpleStruct *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(struct simpleStruct *out, uint32_t x) {
+    out->i1 = 0;
+    out->f1 = 0.f;
+    out->i2 = 1;
+    out->f2 = 1.0f;
+}
+
+struct simpleStruct __attribute__((kernel))
+        root(struct simpleStruct in, uint32_t x) {
+    struct simpleStruct s;
+    s.i1 = in.i1 + x;
+    s.f1 = in.f1 + x;
+    s.i2 = in.i2 + x;
+    s.f2 = in.f2 + x;
+    return s;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i].i1 == (i + ain[i].i1));
+        _RS_ASSERT(aout[i].f1 == (i + ain[i].f1));
+        _RS_ASSERT(aout[i].i2 == (i + ain[i].i2));
+        _RS_ASSERT(aout[i].f2 == (i + ain[i].f2));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_struct_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/math.rs b/java/tests/RsTest/src/com/android/rs/test/math.rs
new file mode 100644
index 0000000..edde9d8
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/math.rs
@@ -0,0 +1,437 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_int_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/math_agree.rs b/java/tests/RsTest/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..5bfbb2b
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,409 @@
+#include "shared.rsh"
+//#pragma rs_fp_relaxed
+
+volatile float x = 0.0f;
+volatile float y = 0.0f;
+volatile float result_add = 0.0f;
+volatile float result_sub = 0.0f;
+volatile float result_mul = 0.0f;
+volatile float result_div = 0.0f;
+
+#define DECLARE_INPUT_SET(type, abbrev)         \
+volatile type    rand_##abbrev##1_0, rand_##abbrev##1_1; \
+volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \
+volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \
+volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1;
+
+#define DECLARE_ALL_INPUT_SETS()    \
+DECLARE_INPUT_SET(float, f);        \
+DECLARE_INPUT_SET(char, sc);        \
+DECLARE_INPUT_SET(uchar, uc);       \
+DECLARE_INPUT_SET(short, ss);       \
+DECLARE_INPUT_SET(ushort, us);      \
+DECLARE_INPUT_SET(int, si);         \
+DECLARE_INPUT_SET(uint, ui);        \
+DECLARE_INPUT_SET(long, sl);        \
+DECLARE_INPUT_SET(ulong, ul);
+
+DECLARE_ALL_INPUT_SETS();
+
+#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func)   \
+volatile type    func##_rand_##abbrev##1_##abbrev##1;                \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##2;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##3;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##4;
+#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func)   \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##1;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##1;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##1;
+
+#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func)    \
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func);    \
+DECLARE_REFERENCE_SET_VEC_VEC(int, si, func);       \
+DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func);
+
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min);
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax);
+
+static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) {
+    int dist = float_dist(actual, expected);
+    rsDebug("float operation did not match!", op_name);
+    rsDebug("v1", v1);
+    rsDebug("v2", v2);
+    rsDebug("Dalvik result", expected);
+    rsDebug("Renderscript result", actual);
+    rsDebug("ULP difference", dist);
+}
+
+static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) {
+    int2 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    rsDebug("float2 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+}
+
+static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) {
+    int3 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    rsDebug("float3 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+}
+
+static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) {
+    int4 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    dist.w = float_dist(actual.w, expected.w);
+    rsDebug("float4 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v1.w", v1.w);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("v2.w", v2.w);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Dalvik result .w", expected.w);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("Renderscript result .w", actual.w);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+    rsDebug("ULP difference .w", dist.w);
+}
+
+static bool f1_almost_equal(float a, float b) {
+    return float_almost_equal(a, b);
+}
+
+static bool f2_almost_equal(float2 a, float2 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y);
+}
+
+
+static bool f3_almost_equal(float3 a, float3 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z);
+}
+
+static bool f4_almost_equal(float4 a, float4 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w);
+}
+
+#define TEST_BASIC_FLOAT_OP(op, opName)                 \
+temp_f1 = x op y;                                       \
+if (! float_almost_equal(temp_f1, result_##opName)) {   \
+    fail_f1(x, y , temp_f1, result_##opName, #opName);  \
+    failed = true;                                      \
+}
+
+#define TEST_FN_FN(func, size)                                                  \
+temp_f##size = func(rand_f##size##_0, rand_f##size##_1);                        \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) {   \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func);   \
+    failed = true;                                                              \
+}
+#define TEST_FN_F(func, size)                                               \
+temp_f##size = func(rand_f##size##_0, rand_f1_1);                           \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) {    \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func);   \
+    failed = true;                                                          \
+}
+
+#define TEST_FN_FN_ALL(func)    \
+TEST_FN_FN(func, 1)             \
+TEST_FN_FN(func, 2)             \
+TEST_FN_FN(func, 3)             \
+TEST_FN_FN(func, 4)
+#define TEST_FN_F_ALL(func) \
+TEST_FN_F(func, 2)          \
+TEST_FN_F(func, 3)          \
+TEST_FN_F(func, 4)
+
+#define TEST_VEC1_VEC1(func, type)                              \
+temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 );    \
+if (temp_##type##1 != func##_rand_##type##1_##type##1) {        \
+    rsDebug(#func " " #type "1 operation did not match!", 0);   \
+    rsDebug("v1", rand_##type##1_0);                            \
+    rsDebug("v2", rand_##type##1_1);                            \
+    rsDebug("Dalvik result", func##_rand_##type##1_##type##1);  \
+    rsDebug("Renderscript result", temp_##type##1);             \
+    failed = true;                                              \
+}
+#define TEST_VEC2_VEC2(func, type)                                      \
+temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 );            \
+if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x             \
+        || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) {   \
+    rsDebug(#func " " #type "2 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##2_0 .x);                               \
+    rsDebug("v1.y", rand_##type##2_0 .y);                               \
+    rsDebug("v2.x", rand_##type##2_1 .x);                               \
+    rsDebug("v2.y", rand_##type##2_1 .y);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y);    \
+    rsDebug("Renderscript result .x", temp_##type##2 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##2 .y);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC3_VEC3(func, type)                                      \
+temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 );            \
+if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x             \
+        || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y      \
+        || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) {   \
+    rsDebug(#func " " #type "3 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##3_0 .x);                               \
+    rsDebug("v1.y", rand_##type##3_0 .y);                               \
+    rsDebug("v1.z", rand_##type##3_0 .z);                               \
+    rsDebug("v2.x", rand_##type##3_1 .x);                               \
+    rsDebug("v2.y", rand_##type##3_1 .y);                               \
+    rsDebug("v2.z", rand_##type##3_1 .z);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z);    \
+    rsDebug("Renderscript result .x", temp_##type##3 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##3 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##3 .z);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC4_VEC4(func, type)                                      \
+temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 );            \
+if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x             \
+        || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y      \
+        || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z      \
+        || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) {   \
+    rsDebug(#func " " #type "4 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##4_0 .x);                               \
+    rsDebug("v1.y", rand_##type##4_0 .y);                               \
+    rsDebug("v1.z", rand_##type##4_0 .z);                               \
+    rsDebug("v1.w", rand_##type##4_0 .w);                               \
+    rsDebug("v2.x", rand_##type##4_1 .x);                               \
+    rsDebug("v2.y", rand_##type##4_1 .y);                               \
+    rsDebug("v2.z", rand_##type##4_1 .z);                               \
+    rsDebug("v2.w", rand_##type##4_1 .w);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z);    \
+    rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w);    \
+    rsDebug("Renderscript result .x", temp_##type##4 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##4 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##4 .z);               \
+    rsDebug("Renderscript result .w", temp_##type##4 .w);               \
+    failed = true;                                                      \
+}
+
+#define TEST_SC1_SC1(func)  TEST_VEC1_VEC1(func, sc)
+#define TEST_SC2_SC2(func)  TEST_VEC2_VEC2(func, sc)
+#define TEST_SC3_SC3(func)  TEST_VEC3_VEC3(func, sc)
+#define TEST_SC4_SC4(func)  TEST_VEC4_VEC4(func, sc)
+
+#define TEST_UC1_UC1(func)  TEST_VEC1_VEC1(func, uc)
+#define TEST_UC2_UC2(func)  TEST_VEC2_VEC2(func, uc)
+#define TEST_UC3_UC3(func)  TEST_VEC3_VEC3(func, uc)
+#define TEST_UC4_UC4(func)  TEST_VEC4_VEC4(func, uc)
+
+#define TEST_SS1_SS1(func)  TEST_VEC1_VEC1(func, ss)
+#define TEST_SS2_SS2(func)  TEST_VEC2_VEC2(func, ss)
+#define TEST_SS3_SS3(func)  TEST_VEC3_VEC3(func, ss)
+#define TEST_SS4_SS4(func)  TEST_VEC4_VEC4(func, ss)
+
+#define TEST_US1_US1(func)  TEST_VEC1_VEC1(func, us)
+#define TEST_US2_US2(func)  TEST_VEC2_VEC2(func, us)
+#define TEST_US3_US3(func)  TEST_VEC3_VEC3(func, us)
+#define TEST_US4_US4(func)  TEST_VEC4_VEC4(func, us)
+
+#define TEST_SI1_SI1(func)  TEST_VEC1_VEC1(func, si)
+#define TEST_SI2_SI2(func)  TEST_VEC2_VEC2(func, si)
+#define TEST_SI3_SI3(func)  TEST_VEC3_VEC3(func, si)
+#define TEST_SI4_SI4(func)  TEST_VEC4_VEC4(func, si)
+
+#define TEST_UI1_UI1(func)  TEST_VEC1_VEC1(func, ui)
+#define TEST_UI2_UI2(func)  TEST_VEC2_VEC2(func, ui)
+#define TEST_UI3_UI3(func)  TEST_VEC3_VEC3(func, ui)
+#define TEST_UI4_UI4(func)  TEST_VEC4_VEC4(func, ui)
+
+#define TEST_SL1_SL1(func)  TEST_VEC1_VEC1(func, sl)
+#define TEST_SL2_SL2(func)  TEST_VEC2_VEC2(func, sl)
+#define TEST_SL3_SL3(func)  TEST_VEC3_VEC3(func, sl)
+#define TEST_SL4_SL4(func)  TEST_VEC4_VEC4(func, sl)
+
+#define TEST_UL1_UL1(func)  TEST_VEC1_VEC1(func, ul)
+#define TEST_UL2_UL2(func)  TEST_VEC2_VEC2(func, ul)
+#define TEST_UL3_UL3(func)  TEST_VEC3_VEC3(func, ul)
+#define TEST_UL4_UL4(func)  TEST_VEC4_VEC4(func, ul)
+
+#define TEST_SC_SC_ALL(func)    \
+TEST_SC1_SC1(func)              \
+TEST_SC2_SC2(func)              \
+TEST_SC3_SC3(func)              \
+TEST_SC4_SC4(func)
+#define TEST_UC_UC_ALL(func)    \
+TEST_UC1_UC1(func)              \
+TEST_UC2_UC2(func)              \
+TEST_UC3_UC3(func)              \
+TEST_UC4_UC4(func)
+
+#define TEST_SS_SS_ALL(func)    \
+TEST_SS1_SS1(func)              \
+TEST_SS2_SS2(func)              \
+TEST_SS3_SS3(func)              \
+TEST_SS4_SS4(func)
+#define TEST_US_US_ALL(func)    \
+TEST_US1_US1(func)              \
+TEST_US2_US2(func)              \
+TEST_US3_US3(func)              \
+TEST_US4_US4(func)
+#define TEST_SI_SI_ALL(func)    \
+TEST_SI1_SI1(func)              \
+TEST_SI2_SI2(func)              \
+TEST_SI3_SI3(func)              \
+TEST_SI4_SI4(func)
+#define TEST_UI_UI_ALL(func)    \
+TEST_UI1_UI1(func)              \
+TEST_UI2_UI2(func)              \
+TEST_UI3_UI3(func)              \
+TEST_UI4_UI4(func)
+#define TEST_SL_SL_ALL(func)    \
+TEST_SL1_SL1(func)              \
+TEST_SL2_SL2(func)              \
+TEST_SL3_SL3(func)              \
+TEST_SL4_SL4(func)
+#define TEST_UL_UL_ALL(func)    \
+TEST_UL1_UL1(func)              \
+TEST_UL2_UL2(func)              \
+TEST_UL3_UL3(func)              \
+TEST_UL4_UL4(func)
+
+#define TEST_VEC_VEC_ALL(func)  \
+TEST_FN_FN_ALL(func)            \
+TEST_SC_SC_ALL(func)            \
+TEST_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
+TEST_UI_UI_ALL(func)
+
+// TODO:  add long types to ALL macro
+#if 0
+TEST_SL_SL_ALL(func)            \
+TEST_UL_UL_ALL(func)
+#endif
+
+#define DECLARE_TEMP_SET(type, abbrev)  \
+volatile type    temp_##abbrev##1;               \
+volatile type##2 temp_##abbrev##2;               \
+volatile type##3 temp_##abbrev##3;               \
+volatile type##4 temp_##abbrev##4;
+
+#define DECLARE_ALL_TEMP_SETS() \
+DECLARE_TEMP_SET(float, f);     \
+DECLARE_TEMP_SET(char, sc);     \
+DECLARE_TEMP_SET(uchar, uc);    \
+DECLARE_TEMP_SET(short, ss);    \
+DECLARE_TEMP_SET(ushort, us);   \
+DECLARE_TEMP_SET(int, si);      \
+DECLARE_TEMP_SET(uint, ui);     \
+DECLARE_TEMP_SET(long, sl);     \
+DECLARE_TEMP_SET(ulong, ul);
+
+static bool test_math_agree() {
+    bool failed = false;
+
+    DECLARE_ALL_TEMP_SETS();
+
+    TEST_BASIC_FLOAT_OP(+, add);
+    TEST_BASIC_FLOAT_OP(-, sub);
+    TEST_BASIC_FLOAT_OP(*, mul);
+    TEST_BASIC_FLOAT_OP(/, div);
+
+    TEST_VEC_VEC_ALL(min);
+    TEST_VEC_VEC_ALL(max);
+    TEST_FN_FN_ALL(fmin);
+    TEST_FN_F_ALL(fmin);
+    TEST_FN_FN_ALL(fmax);
+    TEST_FN_F_ALL(fmax);
+
+    if (failed) {
+        rsDebug("test_math_agree FAILED", 0);
+    }
+    else {
+        rsDebug("test_math_agree PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_agree_test() {
+    bool failed = false;
+    failed |= test_math_agree();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/math_conformance.rs b/java/tests/RsTest/src/com/android/rs/test/math_conformance.rs
new file mode 100644
index 0000000..2d62f34
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/math_conformance.rs
@@ -0,0 +1,57 @@
+#include "shared.rsh"
+
+// Testing math conformance
+
+static bool test_rootn() {
+    bool failed = false;
+
+    // rootn(x, 0) -> NaN
+    _RS_ASSERT(isnan(rootn(1.0f, 0)));
+
+    // rootn(+/-0, n) -> +/-inf for odd n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -3)));
+    _RS_ASSERT(isneginf(rootn(-0.f, -3)));
+
+    // rootn(+/-0, n) -> +inf for even n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -8)));
+    _RS_ASSERT(isposinf(rootn(-0.f, -8)));
+
+    // rootn(+/-0, n) -> +/-0 for odd n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 3)));
+    _RS_ASSERT(isnegzero(rootn(-0.f, 3)));
+
+    // rootn(+/-0, n) -> +0 for even n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 8)));
+    _RS_ASSERT(isposzero(rootn(-0.f, 8)));
+
+    // rootn(x, n) -> NaN for x < 0 and even n
+    _RS_ASSERT(isnan(rootn(-10000.f, -4)));
+    _RS_ASSERT(isnan(rootn(-10000.f, 4)));
+
+    // rootn(x, n) -> value for x < 0 and odd n
+    _RS_ASSERT(!isnan(rootn(-10000.f, -3)));
+    _RS_ASSERT(!isnan(rootn(-10000.f, 3)));
+
+    if (failed) {
+        rsDebug("test_rootn FAILED", -1);
+    }
+    else {
+        rsDebug("test_rootn PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_conformance_test() {
+    bool failed = false;
+    failed |= test_rootn();
+
+    if (failed) {
+        rsDebug("math_conformance_test FAILED", -1);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("math_conformance_test PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/mesh.rs b/java/tests/RsTest/src/com/android/rs/test/mesh.rs
new file mode 100644
index 0000000..1354897
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/mesh.rs
@@ -0,0 +1,64 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_mesh mesh;
+rs_allocation vertexAlloc0;
+rs_allocation vertexAlloc1;
+
+rs_allocation indexAlloc0;
+rs_allocation indexAlloc2;
+
+static bool test_mesh_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsgMeshGetVertexAllocationCount(mesh) == 2);
+    _RS_ASSERT(rsgMeshGetPrimitiveCount(mesh) == 3);
+
+    rs_allocation meshV0 = rsgMeshGetVertexAllocation(mesh, 0);
+    rs_allocation meshV1 = rsgMeshGetVertexAllocation(mesh, 1);
+    rs_allocation meshV2 = rsgMeshGetVertexAllocation(mesh, 2);
+    _RS_ASSERT(meshV0.p == vertexAlloc0.p);
+    _RS_ASSERT(meshV1.p == vertexAlloc1.p);
+    _RS_ASSERT(!rsIsObject(meshV2));
+
+    rs_allocation meshI0 = rsgMeshGetIndexAllocation(mesh, 0);
+    rs_allocation meshI1 = rsgMeshGetIndexAllocation(mesh, 1);
+    rs_allocation meshI2 = rsgMeshGetIndexAllocation(mesh, 2);
+    rs_allocation meshI3 = rsgMeshGetIndexAllocation(mesh, 3);
+    _RS_ASSERT(meshI0.p == indexAlloc0.p);
+    _RS_ASSERT(!rsIsObject(meshI1));
+    _RS_ASSERT(meshI2.p == indexAlloc2.p);
+    _RS_ASSERT(!rsIsObject(meshI3));
+
+    rs_primitive p0 = rsgMeshGetPrimitive(mesh, 0);
+    rs_primitive p1 = rsgMeshGetPrimitive(mesh, 1);
+    rs_primitive p2 = rsgMeshGetPrimitive(mesh, 2);
+    rs_primitive p3 = rsgMeshGetPrimitive(mesh, 3);
+
+    _RS_ASSERT(p0 == RS_PRIMITIVE_POINT);
+    _RS_ASSERT(p1 == RS_PRIMITIVE_LINE);
+    _RS_ASSERT(p2 == RS_PRIMITIVE_TRIANGLE);
+    _RS_ASSERT(p3 == RS_PRIMITIVE_INVALID);
+
+    if (failed) {
+        rsDebug("test_mesh_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_mesh_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void mesh_test() {
+    bool failed = false;
+    failed |= test_mesh_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/min.rs b/java/tests/RsTest/src/com/android/rs/test/min.rs
new file mode 100644
index 0000000..4b92763
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/min.rs
@@ -0,0 +1,20 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+volatile uchar2 res_uc_2 = 1;
+volatile uchar2 src1_uc_2 = 1;
+volatile uchar2 src2_uc_2 = 1;
+
+void min_test() {
+    bool failed = false;
+
+    res_uc_2 = min(src1_uc_2, src2_uc_2);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/noroot.rs b/java/tests/RsTest/src/com/android/rs/test/noroot.rs
new file mode 100644
index 0000000..2c807bd
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/noroot.rs
@@ -0,0 +1,45 @@
+#include "shared.rsh"
+
+rs_allocation aRaw;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    *out = 99 + x + y * dimX;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void noroot_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/primitives.rs b/java/tests/RsTest/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..ce451da
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool test_primitive_types(uint32_t index) {
+    bool failed = false;
+    start();
+
+    _RS_ASSERT(floatTest == 2.99f);
+    _RS_ASSERT(doubleTest == 3.05);
+    _RS_ASSERT(charTest == -16);
+    _RS_ASSERT(shortTest == -32);
+    _RS_ASSERT(intTest == -64);
+    _RS_ASSERT(longTest == 17179869185l);
+    _RS_ASSERT(longlongTest == 68719476735l);
+
+    _RS_ASSERT(ucharTest == 8);
+    _RS_ASSERT(ushortTest == 16);
+    _RS_ASSERT(uintTest == 32);
+    _RS_ASSERT(ulongTest == 4611686018427387903L);
+    _RS_ASSERT(int64_tTest == -17179869184l);
+    _RS_ASSERT(uint64_tTest == 117179869185l);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_primitives FAILED", time);
+    }
+    else {
+        rsDebug("test_primitives PASSED", time);
+    }
+
+    return failed;
+}
+
+void primitives_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_primitive_types(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/program_raster.rs b/java/tests/RsTest/src/com/android/rs/test/program_raster.rs
new file mode 100644
index 0000000..3d6b502
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/program_raster.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_program_raster pointSpriteEnabled;
+rs_program_raster cullMode;
+
+static bool test_program_raster_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsgProgramRasterIsPointSpriteEnabled(pointSpriteEnabled) == true);
+    _RS_ASSERT(rsgProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
+
+    _RS_ASSERT(rsgProgramRasterIsPointSpriteEnabled(cullMode) == false);
+    _RS_ASSERT(rsgProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
+
+    if (failed) {
+        rsDebug("test_program_raster_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_program_raster_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void program_raster_test() {
+    bool failed = false;
+    failed |= test_program_raster_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/program_store.rs b/java/tests/RsTest/src/com/android/rs/test/program_store.rs
new file mode 100644
index 0000000..2ae5636
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/program_store.rs
@@ -0,0 +1,128 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_program_store ditherEnable;
+rs_program_store colorRWriteEnable;
+rs_program_store colorGWriteEnable;
+rs_program_store colorBWriteEnable;
+rs_program_store colorAWriteEnable;
+rs_program_store blendSrc;
+rs_program_store blendDst;
+rs_program_store depthWriteEnable;
+rs_program_store depthFunc;
+
+static bool test_program_store_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(depthWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorRWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorGWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorBWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( colorAWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(ditherEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
+
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreIsDepthMaskEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskRedEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskGreenEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskBlueEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsColorMaskAlphaEnabled( blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreIsDitherEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
+
+    if (failed) {
+        rsDebug("test_program_store_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_program_store_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void program_store_test() {
+    bool failed = false;
+    failed |= test_program_store_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/refcount.rs b/java/tests/RsTest/src/com/android/rs/test/refcount.rs
new file mode 100644
index 0000000..4ea70e2
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/refcount.rs
@@ -0,0 +1,13 @@
+#include "shared.rsh"
+
+// Testing reference counting of RS object types
+
+rs_allocation globalA;
+static rs_allocation staticGlobalA;
+
+void refcount_test() {
+    staticGlobalA = globalA;
+    rsClearObject(&globalA);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/rsdebug.rs b/java/tests/RsTest/src/com/android/rs/test/rsdebug.rs
new file mode 100644
index 0000000..68ac168
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/rsdebug.rs
@@ -0,0 +1,62 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+float2 float2Test = {2.99f, 12.99f};
+float3 float3Test = {3.99f, 13.99f, 23.99f};
+float4 float4Test = {4.99f, 14.99f, 24.99f, 34.99f};
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    // For this reason, none of the outputs are actually checked.
+
+    rsDebug("floatTest", floatTest);
+    rsDebug("float2Test", float2Test);
+    rsDebug("float3Test", float3Test);
+    rsDebug("float4Test", float4Test);
+    rsDebug("doubleTest", doubleTest);
+    rsDebug("charTest", charTest);
+    rsDebug("shortTest", shortTest);
+    rsDebug("intTest", intTest);
+    rsDebug("longTest", longTest);
+    rsDebug("longlongTest", longlongTest);
+
+    rsDebug("ucharTest", ucharTest);
+    rsDebug("ushortTest", ushortTest);
+    rsDebug("uintTest", uintTest);
+    rsDebug("ulongTest", ulongTest);
+    rsDebug("int64_tTest", int64_tTest);
+    rsDebug("uint64_tTest", uint64_tTest);
+
+    return failed;
+}
+
+void test_rsdebug(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rsdebug_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rsdebug_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/rslist.rs b/java/tests/RsTest/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..d8663fb
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,107 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test)
+
+#include "rs_graphics.rsh"
+
+float gDY;
+
+rs_font gFont;
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
+void init() {
+    gDY = 0.0f;
+}
+
+int textPos = 0;
+
+int root(void) {
+
+    rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    rsgClearDepth(1.0f);
+
+    textPos -= (int)gDY*2;
+    gDY *= 0.95;
+
+    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+    rsgBindFont(gFont);
+
+    rs_allocation listAlloc;
+    listAlloc = rsGetAllocation(gList);
+    int allocSize = rsAllocationGetDimX(listAlloc);
+
+    int width = rsgGetWidth();
+    int height = rsgGetHeight();
+
+    int itemHeight = 80;
+    int totalItemHeight = itemHeight * allocSize;
+
+    /* Prevent scrolling above the top of the list */
+    int firstItem = height - totalItemHeight;
+    if (firstItem < 0) {
+        firstItem = 0;
+    }
+
+    /* Prevent scrolling past the last line of the list */
+    int lastItem = -1 * (totalItemHeight - height);
+    if (lastItem > 0) {
+        lastItem = 0;
+    }
+
+    if (textPos > firstItem) {
+        textPos = firstItem;
+    }
+    else if (textPos < lastItem) {
+        textPos = lastItem;
+    }
+
+    int currentYPos = itemHeight + textPos;
+
+    for(int i = 0; i < allocSize; i ++) {
+        if(currentYPos - itemHeight > height) {
+            break;
+        }
+
+        if(currentYPos > 0) {
+            switch(gList[i].result) {
+                case 1: /* Passed */
+                    rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f);
+                    break;
+                case -1: /* Failed */
+                    rsgFontColor(0.9f, 0.5f, 0.5f, 1.0f);
+                    break;
+                case 0: /* Still Testing */
+                    rsgFontColor(0.9f, 0.9f, 0.5f, 1.0f);
+                    break;
+                default: /* Unknown */
+                    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+                    break;
+            }
+            rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0);
+            rsgDrawText(gList[i].text, 30, currentYPos - 32);
+        }
+        currentYPos += itemHeight;
+    }
+
+    return 10;
+}
diff --git a/java/tests/RsTest/src/com/android/rs/test/rstime.rs b/java/tests/RsTest/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..7be955d
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (since we set America/Los_Angeles localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/rstypes.rs b/java/tests/RsTest/src/com/android/rs/test/rstypes.rs
new file mode 100644
index 0000000..22d9c13
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/rstypes.rs
@@ -0,0 +1,79 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element elementTest;
+rs_type typeTest;
+rs_allocation allocationTest;
+rs_sampler samplerTest;
+rs_script scriptTest;
+rs_mesh meshTest;
+rs_program_fragment program_fragmentTest;
+rs_program_vertex program_vertexTest;
+rs_program_raster program_rasterTest;
+rs_program_store program_storeTest;
+rs_font fontTest;
+
+rs_matrix4x4 matrix4x4Test;
+rs_matrix3x3 matrix3x3Test;
+rs_matrix2x2 matrix2x2Test;
+
+struct my_struct {
+    int i;
+    rs_font fontTestStruct;
+};
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_matrix4x4 matrix4x4TestLocal;
+    rs_matrix3x3 matrix3x3TestLocal;
+    rs_matrix2x2 matrix2x2TestLocal;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    rs_element elementTestLocal;
+    rs_type typeTestLocal;
+    rs_allocation allocationTestLocal;
+    rs_sampler samplerTestLocal;
+    rs_script scriptTestLocal;
+    rs_mesh meshTestLocal;
+    rs_program_fragment program_fragmentTestLocal;
+    rs_program_vertex program_vertexTestLocal;
+    rs_program_raster program_rasterTestLocal;
+    rs_program_store program_storeTestLocal;
+    rs_font fontTestLocal;
+
+    rs_font fontTestLocalArray[4];
+
+    rs_font fontTestLocalPreInit = fontTest;
+
+    struct my_struct structTest;
+
+    fontTestLocal = fontTest;
+    //allocationTestLocal = allocationTest;
+
+    fontTest = fontTestLocal;
+    //allocationTest = allocationTestLocal;
+
+    /*for (int i = 0; i < 4; i++) {
+        fontTestLocalArray[i] = fontTestLocal;
+    }*/
+
+    /*fontTest = fontTestLocalArray[3];*/
+
+    return failed;
+}
+
+void test_rstypes(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstypes_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstypes_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/sampler.rs b/java/tests/RsTest/src/com/android/rs/test/sampler.rs
new file mode 100644
index 0000000..ff1c0a7
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/sampler.rs
@@ -0,0 +1,63 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+rs_sampler minification;
+rs_sampler magnification;
+rs_sampler wrapS;
+rs_sampler wrapT;
+rs_sampler anisotropy;
+
+static bool test_sampler_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
+    _RS_ASSERT(rsSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(minification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
+    _RS_ASSERT(rsSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(magnification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapS) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapT) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(anisotropy) == 8.0f);
+
+    if (failed) {
+        rsDebug("test_sampler_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_sampler_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void sampler_test() {
+    bool failed = false;
+    failed |= test_sampler_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/shared.rsh b/java/tests/RsTest/src/com/android/rs/test/shared.rsh
new file mode 100644
index 0000000..3adc999
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/shared.rsh
@@ -0,0 +1,114 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+static const int iposinf = 0x7f800000;
+static const int ineginf = 0xff800000;
+
+static const float posinf() {
+    float f = *((float*)&iposinf);
+    return f;
+}
+
+static const float neginf() {
+    float f = *((float*)&ineginf);
+    return f;
+}
+
+static bool isposinf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == iposinf);
+}
+
+static bool isneginf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == ineginf);
+}
+
+static bool isnan(float f) {
+    int i = *((int*)(void*)&f);
+    return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff));
+}
+
+static bool isposzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x00000000);
+}
+
+static bool isnegzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x80000000);
+}
+
+static bool iszero(float f) {
+    return isposzero(f) || isnegzero(f);
+}
+
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/struct.rs b/java/tests/RsTest/src/com/android/rs/test/struct.rs
new file mode 100644
index 0000000..1cd728e
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/struct.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+typedef struct Point2 {
+   int x;
+   int y;
+} Point_2;
+Point_2 *point2;
+
+static bool test_Point_2(int expected) {
+    bool failed = false;
+
+    rsDebug("Point: ", point2[0].x, point2[0].y);
+    _RS_ASSERT(point2[0].x == expected);
+    _RS_ASSERT(point2[0].y == expected);
+
+    if (failed) {
+        rsDebug("test_Point_2 FAILED", 0);
+    }
+    else {
+        rsDebug("test_Point_2 PASSED", 0);
+    }
+
+    return failed;
+}
+
+void struct_test(int expected) {
+    bool failed = false;
+    failed |= test_Point_2(expected);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/test_root.rs b/java/tests/RsTest/src/com/android/rs/test/test_root.rs
new file mode 100644
index 0000000..6dc83ba
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/test_root.rs
@@ -0,0 +1,23 @@
+// Fountain test script
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test)
+
+#pragma stateFragment(parent)
+
+#include "rs_graphics.rsh"
+
+
+typedef struct TestResult {
+    rs_allocation name;
+    bool pass;
+    float score;
+} TestResult_t;
+TestResult_t *results;
+
+int root() {
+
+    return 0;
+}
+
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/unsigned.rs b/java/tests/RsTest/src/com/android/rs/test/unsigned.rs
new file mode 100644
index 0000000..2c056f4
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/unsigned.rs
@@ -0,0 +1,36 @@
+#include "shared.rsh"
+
+// Testing unsigned types for Bug 6764163
+unsigned int ui = 37;
+unsigned char uc = 5;
+
+static bool test_unsigned() {
+    bool failed = false;
+
+    rsDebug("ui", ui);
+    rsDebug("uc", uc);
+    _RS_ASSERT(ui == 0x7fffffff);
+    _RS_ASSERT(uc == 129);
+
+    if (failed) {
+        rsDebug("test_unsigned FAILED", -1);
+    }
+    else {
+        rsDebug("test_unsigned PASSED", 0);
+    }
+
+    return failed;
+}
+
+void unsigned_test() {
+    bool failed = false;
+    failed |= test_unsigned();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest/src/com/android/rs/test/vector.rs b/java/tests/RsTest/src/com/android/rs/test/vector.rs
new file mode 100644
index 0000000..0430a2f
--- /dev/null
+++ b/java/tests/RsTest/src/com/android/rs/test/vector.rs
@@ -0,0 +1,198 @@
+#include "shared.rsh"
+
+// Testing vector types
+float2 f2 = { 1.0f, 2.0f };
+float3 f3 = { 1.0f, 2.0f, 3.0f };
+float4 f4 = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+double2 d2 = { 1.0, 2.0 };
+double3 d3 = { 1.0, 2.0, 3.0 };
+double4 d4 = { 1.0, 2.0, 3.0, 4.0 };
+
+char2 i8_2 = { 1, 2 };
+char3 i8_3 = { 1, 2, 3 };
+char4 i8_4 = { 1, 2, 3, 4 };
+
+uchar2 u8_2 = { 1, 2 };
+uchar3 u8_3 = { 1, 2, 3 };
+uchar4 u8_4 = { 1, 2, 3, 4 };
+
+short2 i16_2 = { 1, 2 };
+short3 i16_3 = { 1, 2, 3 };
+short4 i16_4 = { 1, 2, 3, 4 };
+
+ushort2 u16_2 = { 1, 2 };
+ushort3 u16_3 = { 1, 2, 3 };
+ushort4 u16_4 = { 1, 2, 3, 4 };
+
+int2 i32_2 = { 1, 2 };
+int3 i32_3 = { 1, 2, 3 };
+int4 i32_4 = { 1, 2, 3, 4 };
+
+uint2 u32_2 = { 1, 2 };
+uint3 u32_3 = { 1, 2, 3 };
+uint4 u32_4 = { 1, 2, 3, 4 };
+
+long2 i64_2 = { 1, 2 };
+long3 i64_3 = { 1, 2, 3 };
+long4 i64_4 = { 1, 2, 3, 4 };
+
+ulong2 u64_2 = { 1, 2 };
+ulong3 u64_3 = { 1, 2, 3 };
+ulong4 u64_4 = { 1, 2, 3, 4 };
+
+static bool test_vector_types() {
+    bool failed = false;
+
+    rsDebug("Testing F32", 0);
+    _RS_ASSERT(f2.x == 2.99f);
+    _RS_ASSERT(f2.y == 3.99f);
+
+    _RS_ASSERT(f3.x == 2.99f);
+    _RS_ASSERT(f3.y == 3.99f);
+    _RS_ASSERT(f3.z == 4.99f);
+
+    _RS_ASSERT(f4.x == 2.99f);
+    _RS_ASSERT(f4.y == 3.99f);
+    _RS_ASSERT(f4.z == 4.99f);
+    _RS_ASSERT(f4.w == 5.99f);
+
+    rsDebug("Testing F64", 0);
+    _RS_ASSERT(d2.x == 2.99);
+    _RS_ASSERT(d2.y == 3.99);
+
+    _RS_ASSERT(d3.x == 2.99);
+    _RS_ASSERT(d3.y == 3.99);
+    _RS_ASSERT(d3.z == 4.99);
+
+    _RS_ASSERT(d4.x == 2.99);
+    _RS_ASSERT(d4.y == 3.99);
+    _RS_ASSERT(d4.z == 4.99);
+    _RS_ASSERT(d4.w == 5.99);
+
+    rsDebug("Testing I8", 0);
+    _RS_ASSERT(i8_2.x == 2);
+    _RS_ASSERT(i8_2.y == 3);
+
+    _RS_ASSERT(i8_3.x == 2);
+    _RS_ASSERT(i8_3.y == 3);
+    _RS_ASSERT(i8_3.z == 4);
+
+    _RS_ASSERT(i8_4.x == 2);
+    _RS_ASSERT(i8_4.y == 3);
+    _RS_ASSERT(i8_4.z == 4);
+    _RS_ASSERT(i8_4.w == 5);
+
+    rsDebug("Testing U8", 0);
+    _RS_ASSERT(u8_2.x == 2);
+    _RS_ASSERT(u8_2.y == 3);
+
+    _RS_ASSERT(u8_3.x == 2);
+    _RS_ASSERT(u8_3.y == 3);
+    _RS_ASSERT(u8_3.z == 4);
+
+    _RS_ASSERT(u8_4.x == 2);
+    _RS_ASSERT(u8_4.y == 3);
+    _RS_ASSERT(u8_4.z == 4);
+    _RS_ASSERT(u8_4.w == 5);
+
+    rsDebug("Testing I16", 0);
+    _RS_ASSERT(i16_2.x == 2);
+    _RS_ASSERT(i16_2.y == 3);
+
+    _RS_ASSERT(i16_3.x == 2);
+    _RS_ASSERT(i16_3.y == 3);
+    _RS_ASSERT(i16_3.z == 4);
+
+    _RS_ASSERT(i16_4.x == 2);
+    _RS_ASSERT(i16_4.y == 3);
+    _RS_ASSERT(i16_4.z == 4);
+    _RS_ASSERT(i16_4.w == 5);
+
+    rsDebug("Testing U16", 0);
+    _RS_ASSERT(u16_2.x == 2);
+    _RS_ASSERT(u16_2.y == 3);
+
+    _RS_ASSERT(u16_3.x == 2);
+    _RS_ASSERT(u16_3.y == 3);
+    _RS_ASSERT(u16_3.z == 4);
+
+    _RS_ASSERT(u16_4.x == 2);
+    _RS_ASSERT(u16_4.y == 3);
+    _RS_ASSERT(u16_4.z == 4);
+    _RS_ASSERT(u16_4.w == 5);
+
+    rsDebug("Testing I32", 0);
+    _RS_ASSERT(i32_2.x == 2);
+    _RS_ASSERT(i32_2.y == 3);
+
+    _RS_ASSERT(i32_3.x == 2);
+    _RS_ASSERT(i32_3.y == 3);
+    _RS_ASSERT(i32_3.z == 4);
+
+    _RS_ASSERT(i32_4.x == 2);
+    _RS_ASSERT(i32_4.y == 3);
+    _RS_ASSERT(i32_4.z == 4);
+    _RS_ASSERT(i32_4.w == 5);
+
+    rsDebug("Testing U32", 0);
+    _RS_ASSERT(u32_2.x == 2);
+    _RS_ASSERT(u32_2.y == 3);
+
+    _RS_ASSERT(u32_3.x == 2);
+    _RS_ASSERT(u32_3.y == 3);
+    _RS_ASSERT(u32_3.z == 4);
+
+    _RS_ASSERT(u32_4.x == 2);
+    _RS_ASSERT(u32_4.y == 3);
+    _RS_ASSERT(u32_4.z == 4);
+    _RS_ASSERT(u32_4.w == 5);
+
+    rsDebug("Testing I64", 0);
+    _RS_ASSERT(i64_2.x == 2);
+    _RS_ASSERT(i64_2.y == 3);
+
+    _RS_ASSERT(i64_3.x == 2);
+    _RS_ASSERT(i64_3.y == 3);
+    _RS_ASSERT(i64_3.z == 4);
+
+    _RS_ASSERT(i64_4.x == 2);
+    _RS_ASSERT(i64_4.y == 3);
+    _RS_ASSERT(i64_4.z == 4);
+    _RS_ASSERT(i64_4.w == 5);
+
+    rsDebug("Testing U64", 0);
+    _RS_ASSERT(u64_2.x == 2);
+    _RS_ASSERT(u64_2.y == 3);
+
+    _RS_ASSERT(u64_3.x == 2);
+    _RS_ASSERT(u64_3.y == 3);
+    _RS_ASSERT(u64_3.z == 4);
+
+    _RS_ASSERT(u64_4.x == 2);
+    _RS_ASSERT(u64_4.y == 3);
+    _RS_ASSERT(u64_4.z == 4);
+    _RS_ASSERT(u64_4.w == 5);
+
+    if (failed) {
+        rsDebug("test_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void vector_test() {
+    bool failed = false;
+    failed |= test_vector_types();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_11/Android.mk b/java/tests/RsTest_11/Android.mk
new file mode 100644
index 0000000..52d326b
--- /dev/null
+++ b/java/tests/RsTest_11/Android.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RSTest_v11
+LOCAL_SDK_VERSION := 11
+
+include $(BUILD_PACKAGE)
+
+endif
diff --git a/java/tests/RsTest_11/AndroidManifest.xml b/java/tests/RsTest_11/AndroidManifest.xml
new file mode 100644
index 0000000..f4aeda2
--- /dev/null
+++ b/java/tests/RsTest_11/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.test_v11">
+    <uses-sdk android:minSdkVersion="11" />
+    <application 
+        android:label="_RS_Test_v11"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="RSTest_v11"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/RsTest_11/res/drawable/test_pattern.png b/java/tests/RsTest_11/res/drawable/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/java/tests/RsTest_11/res/drawable/test_pattern.png
Binary files differ
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/RSTestCore.java b/java/tests/RsTest_11/src/com/android/rs/test/RSTestCore.java
new file mode 100644
index 0000000..888cfe4
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/RSTestCore.java
@@ -0,0 +1,206 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+public class RSTestCore {
+    int mWidth;
+    int mHeight;
+    Context mCtx;
+
+    public RSTestCore(Context ctx) {
+        mCtx = ctx;
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private Font mFont;
+    ScriptField_ListAllocs_s mListAllocs;
+    int mLastX;
+    int mLastY;
+    private ScriptC_rslist mScript;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        mWidth = width;
+        mHeight = height;
+        stopTesting = false;
+
+        mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist);
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_math(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
+        /*
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
+        unitTests.add(new UnitTest());
+        unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+        for (int i = 0; i < 20; i++) {
+            unitTests.add(new UnitTest(null, "<Pass>", 1));
+        }
+        */
+
+        UnitTest [] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].result;
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+
+        mScript.bind_gList(mListAllocs);
+
+        mFont = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mScript.set_gFont(mFont);
+
+        mRS.bindRootScript(mScript);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                }
+                catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            }
+            else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+
+        if (mListAllocs != null && mScript != null && mRS != null) {
+            mListAllocs.copyAll();
+
+            mScript.bind_gList(mListAllocs);
+            mRS.bindRootScript(mScript);
+        }
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+    public void newTouchPosition(float x, float y, float pressure, int id) {
+    }
+
+    public void onActionDown(int x, int y) {
+        mScript.set_gDY(0.0f);
+        mLastX = x;
+        mLastY = y;
+        refreshTestResults();
+    }
+
+    public void onActionMove(int x, int y) {
+        int dx = mLastX - x;
+        int dy = mLastY - y;
+
+        if (Math.abs(dy) <= 2) {
+            dy = 0;
+        }
+
+        mScript.set_gDY(dy);
+
+        mLastX = x;
+        mLastY = y;
+        refreshTestResults();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/RSTestView.java b/java/tests/RsTest_11/src/com/android/rs/test/RSTestView.java
new file mode 100644
index 0000000..b5bebe9
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/RSTestView.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class RSTestView extends RSSurfaceView {
+
+    private Context mCtx;
+
+    public RSTestView(Context context) {
+        super(context);
+        mCtx = context;
+        //setFocusable(true);
+    }
+
+    private RenderScriptGL mRS;
+    private RSTestCore mRender;
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRS = createRenderScriptGL(sc);
+            mRS.setSurface(holder, w, h);
+            mRender = new RSTestCore(mCtx);
+            mRender.init(mRS, getResources(), w, h);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if(mRS != null) {
+            mRender.cleanup();
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev)
+    {
+        boolean ret = false;
+        int act = ev.getAction();
+        if (act == ev.ACTION_DOWN) {
+            mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+            ret = true;
+        }
+        else if (act == ev.ACTION_MOVE) {
+            mRender.onActionMove((int)ev.getX(), (int)ev.getY());
+            ret = true;
+        }
+
+        return ret;
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/RSTest_v11.java b/java/tests/RsTest_11/src/com/android/rs/test/RSTest_v11.java
new file mode 100644
index 0000000..1dedfce
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/RSTest_v11.java
@@ -0,0 +1,84 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Config;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import java.lang.Runtime;
+
+public class RSTest_v11 extends Activity {
+    //EventListener mListener = new EventListener();
+
+    private static final String LOG_TAG = "libRS_jni";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+
+    private RSTestView mView;
+
+    // get the current looper (from your Activity UI thread for instance
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new RSTestView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onPause();
+        mView.pause();
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UT_fp_mad.java b/java/tests/RsTest_11/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..5d72aa6
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+    private Resources mRes;
+
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS, mRes, R.raw.fp_mad);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_fp_mad_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UT_math.java b/java/tests/RsTest_11/src/com/android/rs/test/UT_math.java
new file mode 100644
index 0000000..7e356f8
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UT_math.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_math extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math s = new ScriptC_math(pRS, mRes, R.raw.math);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UT_primitives.java b/java/tests/RsTest_11/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..dc3efbc
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,104 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+    private Resources mRes;
+
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_primitives s) {
+        float pF = s.get_floatTest();
+        if (pF != 1.99f) {
+            return false;
+        }
+        s.set_floatTest(2.99f);
+
+        double pD = s.get_doubleTest();
+        if (pD != 2.05) {
+            return false;
+        }
+        s.set_doubleTest(3.05);
+
+        byte pC = s.get_charTest();
+        if (pC != -8) {
+            return false;
+        }
+        s.set_charTest((byte)-16);
+
+        short pS = s.get_shortTest();
+        if (pS != -16) {
+            return false;
+        }
+        s.set_shortTest((short)-32);
+
+        int pI = s.get_intTest();
+        if (pI != -32) {
+            return false;
+        }
+        s.set_intTest(-64);
+
+        long pL = s.get_longTest();
+        if (pL != 17179869184l) {
+            return false;
+        }
+        s.set_longTest(17179869185l);
+
+        long puL = s.get_ulongTest();
+        if (puL != 4611686018427387904L) {
+            return false;
+        }
+        s.set_ulongTest(4611686018427387903L);
+
+
+        long pLL = s.get_longlongTest();
+        if (pLL != 68719476736L) {
+            return false;
+        }
+        s.set_longlongTest(68719476735L);
+
+        long pu64 = s.get_uint64_tTest();
+        if (pu64 != 117179869184l) {
+            return false;
+        }
+        s.set_uint64_tTest(117179869185l);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            // initializeGlobals failed
+            result = -1;
+        } else {
+            s.invoke_primitives_test(0, 0);
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UT_rsdebug.java b/java/tests/RsTest_11/src/com/android/rs/test/UT_rsdebug.java
new file mode 100644
index 0000000..00dbaf5
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UT_rsdebug.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rsdebug extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS, mRes, R.raw.rsdebug);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rsdebug(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UT_rstime.java b/java/tests/RsTest_11/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..5b4c399
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UT_rstypes.java b/java/tests/RsTest_11/src/com/android/rs/test/UT_rstypes.java
new file mode 100644
index 0000000..72a97c9
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UT_rstypes.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v11;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstypes extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS, mRes, R.raw.rstypes);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstypes(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/UnitTest.java b/java/tests/RsTest_11/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..b62e535
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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 com.android.rs.test_v11;
+import android.content.Context;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.util.Log;
+
+public class UnitTest extends Thread {
+    public String name;
+    public int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = 1;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = -1;
+                        break;
+                    default:
+                        android.util.Log.v("RenderScript", "Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            if (mItem != null) {
+                mItem.result = result;
+                msgHandled = true;
+                try {
+                    mRSTC.refreshTestResults();
+                }
+                catch (IllegalStateException e) {
+                    /* Ignore the case where our message receiver has been
+                       disconnected. This happens when we leave the application
+                       before it finishes running all of the unit tests. */
+                }
+            }
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/fp_mad.rs b/java/tests/RsTest_11/src/com/android/rs/test/fp_mad.rs
new file mode 100644
index 0000000..b6f2b2a
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/fp_mad.rs
@@ -0,0 +1,174 @@
+#include "shared.rsh"
+
+const int TEST_COUNT = 1;
+
+static float data_f1[1025];
+static float4 data_f4[1025];
+
+static void test_mad4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 80); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = (data_f4[i] * 0.02f +
+                          data_f4[i+1] * 0.04f +
+                          data_f4[i+2] * 0.05f +
+                          data_f4[i+3] * 0.1f +
+                          data_f4[i+4] * 0.2f +
+                          data_f4[i+5] * 0.2f +
+                          data_f4[i+6] * 0.1f +
+                          data_f4[i+7] * 0.05f +
+                          data_f4[i+8] * 0.04f +
+                          data_f4[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad4 M ops", 1000.f / time);
+}
+
+static void test_mad(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 20); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = (data_f1[i] * 0.02f +
+                          data_f1[i+1] * 0.04f +
+                          data_f1[i+2] * 0.05f +
+                          data_f1[i+3] * 0.1f +
+                          data_f1[i+4] * 0.2f +
+                          data_f1[i+5] * 0.2f +
+                          data_f1[i+6] * 0.1f +
+                          data_f1[i+7] * 0.05f +
+                          data_f1[i+8] * 0.04f +
+                          data_f1[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad M ops", 1000.f / time);
+}
+
+static void test_norm(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = normalize(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_norm M ops", 10.f / time);
+}
+
+static void test_sincos4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10 / 4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos4 M ops", 10.f / time);
+}
+
+static void test_sincos(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos M ops", 10.f / time);
+}
+
+static void test_clamp(uint32_t index) {
+    start();
+
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = clamp(data_f1[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp M ops", 100.f / time);
+
+    start();
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            if (data_f1[i] < -1.f) data_f1[i] = -1.f;
+            if (data_f1[i] > -1.f) data_f1[i] = 1.f;
+        }
+    }
+
+    time = end(index);
+    rsDebug("fp_clamp ref M ops", 100.f / time);
+}
+
+static void test_clamp4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100 /4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = clamp(data_f4[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp4 M ops", 100.f / time);
+}
+
+void fp_mad_test(uint32_t index, int test_num) {
+    int x;
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f;
+        data_f4[x].x = (x & 0xf) * 0.1f;
+        data_f4[x].y = (x & 0xf0) * 0.1f;
+        data_f4[x].z = (x & 0x33) * 0.1f;
+        data_f4[x].w = (x & 0x77) * 0.1f;
+    }
+
+    test_mad4(index);
+    test_mad(index);
+
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].x = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].y = (x & 0xf0) * 0.1f + 1.f;
+        data_f4[x].z = (x & 0x33) * 0.1f + 1.f;
+        data_f4[x].w = (x & 0x77) * 0.1f + 1.f;
+    }
+
+    test_norm(index);
+    test_sincos4(index);
+    test_sincos(index);
+    test_clamp4(index);
+    test_clamp(index);
+
+    // TODO Actually verify test result accuracy
+    rsDebug("fp_mad_test PASSED", 0);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/math.rs b/java/tests/RsTest_11/src/com/android/rs/test/math.rs
new file mode 100644
index 0000000..2867be1
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/math.rs
@@ -0,0 +1,348 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define INIT_PREFIX_TYPE(prefix, type)  \
+prefix##_##type##_1 = 1;                \
+prefix##_##type##_2.x = 1;              \
+prefix##_##type##_2.y = 1;              \
+prefix##_##type##_3.x = 1;              \
+prefix##_##type##_3.y = 1;              \
+prefix##_##type##_3.z = 1;              \
+prefix##_##type##_4.x = 1;              \
+prefix##_##type##_4.y = 1;              \
+prefix##_##type##_4.z = 1;              \
+prefix##_##type##_4.w = 1;
+
+#define INIT_TYPE(type)         \
+INIT_PREFIX_TYPE(src1, type)    \
+INIT_PREFIX_TYPE(src2, type)    \
+INIT_PREFIX_TYPE(res, type)
+
+#define INIT_ALL    \
+INIT_TYPE(c);       \
+INIT_TYPE(uc);      \
+INIT_TYPE(s);       \
+INIT_TYPE(us);      \
+INIT_TYPE(i);       \
+INIT_TYPE(ui);
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    INIT_ALL;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/primitives.rs b/java/tests/RsTest_11/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..ce451da
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool test_primitive_types(uint32_t index) {
+    bool failed = false;
+    start();
+
+    _RS_ASSERT(floatTest == 2.99f);
+    _RS_ASSERT(doubleTest == 3.05);
+    _RS_ASSERT(charTest == -16);
+    _RS_ASSERT(shortTest == -32);
+    _RS_ASSERT(intTest == -64);
+    _RS_ASSERT(longTest == 17179869185l);
+    _RS_ASSERT(longlongTest == 68719476735l);
+
+    _RS_ASSERT(ucharTest == 8);
+    _RS_ASSERT(ushortTest == 16);
+    _RS_ASSERT(uintTest == 32);
+    _RS_ASSERT(ulongTest == 4611686018427387903L);
+    _RS_ASSERT(int64_tTest == -17179869184l);
+    _RS_ASSERT(uint64_tTest == 117179869185l);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_primitives FAILED", time);
+    }
+    else {
+        rsDebug("test_primitives PASSED", time);
+    }
+
+    return failed;
+}
+
+void primitives_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_primitive_types(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/rsdebug.rs b/java/tests/RsTest_11/src/com/android/rs/test/rsdebug.rs
new file mode 100644
index 0000000..f7942a5
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/rsdebug.rs
@@ -0,0 +1,56 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    // For this reason, none of the outputs are actually checked.
+
+    rsDebug("floatTest", floatTest);
+    rsDebug("doubleTest", doubleTest);
+    rsDebug("charTest", charTest);
+    rsDebug("shortTest", shortTest);
+    rsDebug("intTest", intTest);
+    rsDebug("longTest", longTest);
+    rsDebug("longlongTest", longlongTest);
+
+    rsDebug("ucharTest", ucharTest);
+    rsDebug("ushortTest", ushortTest);
+    rsDebug("uintTest", uintTest);
+    rsDebug("ulongTest", ulongTest);
+    rsDebug("int64_tTest", int64_tTest);
+    rsDebug("uint64_tTest", uint64_tTest);
+
+    return failed;
+}
+
+void test_rsdebug(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rsdebug_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rsdebug_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/rslist.rs b/java/tests/RsTest_11/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..5b2501f
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,107 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_v11)
+
+#include "rs_graphics.rsh"
+
+float gDY;
+
+rs_font gFont;
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
+void init() {
+    gDY = 0.0f;
+}
+
+int textPos = 0;
+
+int root(int launchID) {
+
+    rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    rsgClearDepth(1.0f);
+
+    textPos -= (int)gDY*2;
+    gDY *= 0.95;
+
+    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+    rsgBindFont(gFont);
+
+    rs_allocation listAlloc;
+    rsSetObject(&listAlloc, rsGetAllocation(gList));
+    int allocSize = rsAllocationGetDimX(listAlloc);
+
+    int width = rsgGetWidth();
+    int height = rsgGetHeight();
+
+    int itemHeight = 80;
+    int totalItemHeight = itemHeight * allocSize;
+
+    /* Prevent scrolling above the top of the list */
+    int firstItem = height - totalItemHeight;
+    if (firstItem < 0) {
+        firstItem = 0;
+    }
+
+    /* Prevent scrolling past the last line of the list */
+    int lastItem = -1 * (totalItemHeight - height);
+    if (lastItem > 0) {
+        lastItem = 0;
+    }
+
+    if (textPos > firstItem) {
+        textPos = firstItem;
+    }
+    else if (textPos < lastItem) {
+        textPos = lastItem;
+    }
+
+    int currentYPos = itemHeight + textPos;
+
+    for(int i = 0; i < allocSize; i ++) {
+        if(currentYPos - itemHeight > height) {
+            break;
+        }
+
+        if(currentYPos > 0) {
+            switch(gList[i].result) {
+                case 1: /* Passed */
+                    rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f);
+                    break;
+                case -1: /* Failed */
+                    rsgFontColor(0.9f, 0.5f, 0.5f, 1.0f);
+                    break;
+                case 0: /* Still Testing */
+                    rsgFontColor(0.9f, 0.9f, 0.5f, 1.0f);
+                    break;
+                default: /* Unknown */
+                    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+                    break;
+            }
+            rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0);
+            rsgDrawText(gList[i].text, 30, currentYPos - 32);
+        }
+        currentYPos += itemHeight;
+    }
+
+    return 10;
+}
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/rstime.rs b/java/tests/RsTest_11/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..5e3e078
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (only valid for PST localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/rstypes.rs b/java/tests/RsTest_11/src/com/android/rs/test/rstypes.rs
new file mode 100644
index 0000000..f3bf244
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/rstypes.rs
@@ -0,0 +1,79 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element elementTest;
+rs_type typeTest;
+rs_allocation allocationTest;
+rs_sampler samplerTest;
+rs_script scriptTest;
+rs_mesh meshTest;
+rs_program_fragment program_fragmentTest;
+rs_program_vertex program_vertexTest;
+rs_program_raster program_rasterTest;
+rs_program_store program_storeTest;
+rs_font fontTest;
+
+rs_matrix4x4 matrix4x4Test;
+rs_matrix3x3 matrix3x3Test;
+rs_matrix2x2 matrix2x2Test;
+
+struct my_struct {
+    int i;
+    rs_font fontTestStruct;
+};
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_matrix4x4 matrix4x4TestLocal;
+    rs_matrix3x3 matrix3x3TestLocal;
+    rs_matrix2x2 matrix2x2TestLocal;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    rs_element elementTestLocal;
+    rs_type typeTestLocal;
+    rs_allocation allocationTestLocal;
+    rs_sampler samplerTestLocal;
+    rs_script scriptTestLocal;
+    rs_mesh meshTestLocal;
+    rs_program_fragment program_fragmentTestLocal;
+    rs_program_vertex program_vertexTestLocal;
+    rs_program_raster program_rasterTestLocal;
+    rs_program_store program_storeTestLocal;
+    rs_font fontTestLocal;
+
+    rs_font fontTestLocalArray[4];
+
+    rs_font fontTestLocalPreInit = fontTest;
+
+    struct my_struct structTest;
+
+    rsSetObject(&fontTestLocal, fontTest);
+    //allocationTestLocal = allocationTest;
+
+    rsSetObject(&fontTest, fontTestLocal);
+    //allocationTest = allocationTestLocal;
+
+    /*for (int i = 0; i < 4; i++) {
+        rsSetObject(&fontTestLocalArray[i], fontTestLocal);
+    }*/
+
+    /*rsSetObject(&fontTest, fontTestLocalArray[3]);*/
+
+    return failed;
+}
+
+void test_rstypes(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstypes_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstypes_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/shared.rsh b/java/tests/RsTest_11/src/com/android/rs/test/shared.rsh
new file mode 100644
index 0000000..6d34481
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/shared.rsh
@@ -0,0 +1,38 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_v11)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
diff --git a/java/tests/RsTest_11/src/com/android/rs/test/test_root.rs b/java/tests/RsTest_11/src/com/android/rs/test/test_root.rs
new file mode 100644
index 0000000..6dc83ba
--- /dev/null
+++ b/java/tests/RsTest_11/src/com/android/rs/test/test_root.rs
@@ -0,0 +1,23 @@
+// Fountain test script
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test)
+
+#pragma stateFragment(parent)
+
+#include "rs_graphics.rsh"
+
+
+typedef struct TestResult {
+    rs_allocation name;
+    bool pass;
+    float score;
+} TestResult_t;
+TestResult_t *results;
+
+int root() {
+
+    return 0;
+}
+
+
diff --git a/java/tests/RsTest_14/Android.mk b/java/tests/RsTest_14/Android.mk
new file mode 100644
index 0000000..a4386a4
--- /dev/null
+++ b/java/tests/RsTest_14/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RSTest_v14
+LOCAL_SDK_VERSION := 14
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/RsTest_14/AndroidManifest.xml b/java/tests/RsTest_14/AndroidManifest.xml
new file mode 100644
index 0000000..1cd9bbd
--- /dev/null
+++ b/java/tests/RsTest_14/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.test_v14">
+    <uses-sdk android:minSdkVersion="14" />
+    <application 
+        android:label="_RS_Test_v14"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="RSTest_v14"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/RsTest_14/res/drawable-nodpi/test_pattern.png b/java/tests/RsTest_14/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/java/tests/RsTest_14/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/RSTestCore.java b/java/tests/RsTest_14/src/com/android/rs/test/RSTestCore.java
new file mode 100644
index 0000000..f1e81a4
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/RSTestCore.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2008-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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+public class RSTestCore {
+    int mWidth;
+    int mHeight;
+    Context mCtx;
+
+    public RSTestCore(Context ctx) {
+        mCtx = ctx;
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private Font mFont;
+    ScriptField_ListAllocs_s mListAllocs;
+    int mLastX;
+    int mLastY;
+    private ScriptC_rslist mScript;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        mWidth = width;
+        mHeight = height;
+        stopTesting = false;
+
+        mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist);
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_refcount(this, mRes, mCtx));
+        unitTests.add(new UT_foreach(this, mRes, mCtx));
+        unitTests.add(new UT_math(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
+        /*
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
+        unitTests.add(new UnitTest());
+        unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+        for (int i = 0; i < 20; i++) {
+            unitTests.add(new UnitTest(null, "<Pass>", 1));
+        }
+        */
+
+        UnitTest [] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].result;
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+
+        mScript.bind_gList(mListAllocs);
+
+        mFont = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mScript.set_gFont(mFont);
+
+        mRS.bindRootScript(mScript);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                }
+                catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            }
+            else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+
+        if (mListAllocs != null && mScript != null && mRS != null) {
+            mListAllocs.copyAll();
+
+            mScript.bind_gList(mListAllocs);
+            mRS.bindRootScript(mScript);
+        }
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+    public void newTouchPosition(float x, float y, float pressure, int id) {
+    }
+
+    public void onActionDown(int x, int y) {
+        mScript.set_gDY(0.0f);
+        mLastX = x;
+        mLastY = y;
+        refreshTestResults();
+    }
+
+    public void onActionMove(int x, int y) {
+        int dx = mLastX - x;
+        int dy = mLastY - y;
+
+        if (Math.abs(dy) <= 2) {
+            dy = 0;
+        }
+
+        mScript.set_gDY(dy);
+
+        mLastX = x;
+        mLastY = y;
+        refreshTestResults();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/RSTestView.java b/java/tests/RsTest_14/src/com/android/rs/test/RSTestView.java
new file mode 100644
index 0000000..40192e4
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/RSTestView.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class RSTestView extends RSSurfaceView {
+
+    private Context mCtx;
+
+    public RSTestView(Context context) {
+        super(context);
+        mCtx = context;
+        //setFocusable(true);
+    }
+
+    private RenderScriptGL mRS;
+    private RSTestCore mRender;
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRS = createRenderScriptGL(sc);
+            mRS.setSurface(holder, w, h);
+            mRender = new RSTestCore(mCtx);
+            mRender.init(mRS, getResources(), w, h);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if(mRS != null) {
+            mRender.cleanup();
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev)
+    {
+        boolean ret = false;
+        int act = ev.getAction();
+        if (act == ev.ACTION_DOWN) {
+            mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+            ret = true;
+        }
+        else if (act == ev.ACTION_MOVE) {
+            mRender.onActionMove((int)ev.getX(), (int)ev.getY());
+            ret = true;
+        }
+
+        return ret;
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/RSTest_v14.java b/java/tests/RsTest_14/src/com/android/rs/test/RSTest_v14.java
new file mode 100644
index 0000000..da09691
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/RSTest_v14.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import java.lang.Runtime;
+
+public class RSTest_v14 extends Activity {
+    //EventListener mListener = new EventListener();
+
+    private static final String LOG_TAG = "RSTest_v14";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private RSTestView mView;
+
+    // get the current looper (from your Activity UI thread for instance
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new RSTestView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onPause();
+        mView.pause();
+    }
+
+    @Override
+    protected void onStop() {
+        // Actually kill the app if we are stopping. We don't want to
+        // continue/resume this test ever. It should always start fresh.
+        finish();
+        super.onStop();
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_alloc.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_alloc.java
new file mode 100644
index 0000000..079fcce
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_alloc.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Alloc", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_alloc s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        int Z = 0;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        s.set_dimZ(Z);
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+        s.set_aRaw(A);
+
+        typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        typeBuilder.setX(X).setY(Y).setFaces(true);
+        Allocation AFaces = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFaces(AFaces);
+        typeBuilder.setFaces(false).setMipmaps(true);
+        Allocation ALOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aLOD(ALOD);
+        typeBuilder.setFaces(true).setMipmaps(true);
+        Allocation AFacesLOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFacesLOD(AFacesLOD);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_alloc s = new ScriptC_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(s.get_aRaw());
+        s.invoke_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_foreach.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_foreach.java
new file mode 100644
index 0000000..31f4114
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_foreach.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_foreach extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aRaw(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach s = new ScriptC_foreach(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(A);
+        s.invoke_verify_root();
+        s.invoke_foreach_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_fp_mad.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..239496a
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+    private Resources mRes;
+
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS, mRes, R.raw.fp_mad);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_fp_mad_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_math.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_math.java
new file mode 100644
index 0000000..7b135c4
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_math.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_math extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math s = new ScriptC_math(pRS, mRes, R.raw.math);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_primitives.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..d3c56f3
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,104 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+    private Resources mRes;
+
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_primitives s) {
+        float pF = s.get_floatTest();
+        if (pF != 1.99f) {
+            return false;
+        }
+        s.set_floatTest(2.99f);
+
+        double pD = s.get_doubleTest();
+        if (pD != 2.05) {
+            return false;
+        }
+        s.set_doubleTest(3.05);
+
+        byte pC = s.get_charTest();
+        if (pC != -8) {
+            return false;
+        }
+        s.set_charTest((byte)-16);
+
+        short pS = s.get_shortTest();
+        if (pS != -16) {
+            return false;
+        }
+        s.set_shortTest((short)-32);
+
+        int pI = s.get_intTest();
+        if (pI != -32) {
+            return false;
+        }
+        s.set_intTest(-64);
+
+        long pL = s.get_longTest();
+        if (pL != 17179869184l) {
+            return false;
+        }
+        s.set_longTest(17179869185l);
+
+        long puL = s.get_ulongTest();
+        if (puL != 4611686018427387904L) {
+            return false;
+        }
+        s.set_ulongTest(4611686018427387903L);
+
+
+        long pLL = s.get_longlongTest();
+        if (pLL != 68719476736L) {
+            return false;
+        }
+        s.set_longlongTest(68719476735L);
+
+        long pu64 = s.get_uint64_tTest();
+        if (pu64 != 117179869184l) {
+            return false;
+        }
+        s.set_uint64_tTest(117179869185l);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            // initializeGlobals failed
+            result = -1;
+        } else {
+            s.invoke_primitives_test(0, 0);
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_refcount.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_refcount.java
new file mode 100644
index 0000000..05a516b
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_refcount.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_refcount extends UnitTest {
+    private Resources mRes;
+
+    protected UT_refcount(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Refcount", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_refcount s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 500;
+        int Y = 700;
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_globalA(A);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        pRS.setMessageHandler(mRsMessage);
+        ScriptC_refcount s = new ScriptC_refcount(pRS, mRes, R.raw.refcount);
+        initializeGlobals(pRS, s);
+        s.invoke_refcount_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_rsdebug.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_rsdebug.java
new file mode 100644
index 0000000..95e92ee
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_rsdebug.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rsdebug extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS, mRes, R.raw.rsdebug);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rsdebug(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_rstime.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..a72ede9
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_rstypes.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_rstypes.java
new file mode 100644
index 0000000..ab96867
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_rstypes.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstypes extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS, mRes, R.raw.rstypes);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstypes(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UT_vector.java b/java/tests/RsTest_14/src/com/android/rs/test/UT_vector.java
new file mode 100644
index 0000000..657413e
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UT_vector.java
@@ -0,0 +1,318 @@
+/*
+ * 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 com.android.rs.test_v14;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_vector extends UnitTest {
+    private Resources mRes;
+
+    protected UT_vector(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Vector", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_vector s) {
+        Float2 F2 = s.get_f2();
+        if (F2.x != 1.0f || F2.y != 2.0f) {
+            return false;
+        }
+        F2.x = 2.99f;
+        F2.y = 3.99f;
+        s.set_f2(F2);
+
+        Float3 F3 = s.get_f3();
+        if (F3.x != 1.0f || F3.y != 2.0f || F3.z != 3.0f) {
+            return false;
+        }
+        F3.x = 2.99f;
+        F3.y = 3.99f;
+        F3.z = 4.99f;
+        s.set_f3(F3);
+
+        Float4 F4 = s.get_f4();
+        if (F4.x != 1.0f || F4.y != 2.0f || F4.z != 3.0f || F4.w != 4.0f) {
+            return false;
+        }
+        F4.x = 2.99f;
+        F4.y = 3.99f;
+        F4.z = 4.99f;
+        F4.w = 5.99f;
+        s.set_f4(F4);
+
+        Double2 D2 = s.get_d2();
+        if (D2.x != 1.0 || D2.y != 2.0) {
+            return false;
+        }
+        D2.x = 2.99;
+        D2.y = 3.99;
+        s.set_d2(D2);
+
+        Double3 D3 = s.get_d3();
+        if (D3.x != 1.0 || D3.y != 2.0 || D3.z != 3.0) {
+            return false;
+        }
+        D3.x = 2.99;
+        D3.y = 3.99;
+        D3.z = 4.99;
+        s.set_d3(D3);
+
+        Double4 D4 = s.get_d4();
+        if (D4.x != 1.0 || D4.y != 2.0 || D4.z != 3.0 || D4.w != 4.0) {
+            return false;
+        }
+        D4.x = 2.99;
+        D4.y = 3.99;
+        D4.z = 4.99;
+        D4.w = 5.99;
+        s.set_d4(D4);
+
+        Byte2 B2 = s.get_i8_2();
+        if (B2.x != 1 || B2.y != 2) {
+            return false;
+        }
+        B2.x = 2;
+        B2.y = 3;
+        s.set_i8_2(B2);
+
+        Byte3 B3 = s.get_i8_3();
+        if (B3.x != 1 || B3.y != 2 || B3.z != 3) {
+            return false;
+        }
+        B3.x = 2;
+        B3.y = 3;
+        B3.z = 4;
+        s.set_i8_3(B3);
+
+        Byte4 B4 = s.get_i8_4();
+        if (B4.x != 1 || B4.y != 2 || B4.z != 3 || B4.w != 4) {
+            return false;
+        }
+        B4.x = 2;
+        B4.y = 3;
+        B4.z = 4;
+        B4.w = 5;
+        s.set_i8_4(B4);
+
+        Short2 S2 = s.get_u8_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_u8_2(S2);
+
+        Short3 S3 = s.get_u8_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_u8_3(S3);
+
+        Short4 S4 = s.get_u8_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_u8_4(S4);
+
+        S2 = s.get_i16_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_i16_2(S2);
+
+        S3 = s.get_i16_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_i16_3(S3);
+
+        S4 = s.get_i16_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_i16_4(S4);
+
+        Int2 I2 = s.get_u16_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_u16_2(I2);
+
+        Int3 I3 = s.get_u16_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_u16_3(I3);
+
+        Int4 I4 = s.get_u16_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_u16_4(I4);
+
+        I2 = s.get_i32_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_i32_2(I2);
+
+        I3 = s.get_i32_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_i32_3(I3);
+
+        I4 = s.get_i32_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_i32_4(I4);
+
+        Long2 L2 = s.get_u32_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u32_2(L2);
+
+        Long3 L3 = s.get_u32_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u32_3(L3);
+
+        Long4 L4 = s.get_u32_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u32_4(L4);
+
+        L2 = s.get_i64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_i64_2(L2);
+
+        L3 = s.get_i64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_i64_3(L3);
+
+        L4 = s.get_i64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_i64_4(L4);
+
+        L2 = s.get_u64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u64_2(L2);
+
+        L3 = s.get_u64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u64_3(L3);
+
+        L4 = s.get_u64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u64_4(L4);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_vector s = new ScriptC_vector(pRS, mRes, R.raw.vector);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            result = -1;
+        } else {
+            s.invoke_vector_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/UnitTest.java b/java/tests/RsTest_14/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..558a252
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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 com.android.rs.test_v14;
+import android.content.Context;
+import android.util.Log;
+import android.renderscript.RenderScript.RSMessageHandler;
+
+public class UnitTest extends Thread {
+    public String name;
+    public int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
+    }
+
+    protected void _RS_ASSERT(String message, boolean b) {
+        if(b == false) {
+            result = -1;
+            Log.e(name, message + " FAILED");
+        }
+    }
+
+    protected void updateUI() {
+        if (mItem != null) {
+            mItem.result = result;
+            msgHandled = true;
+            try {
+                mRSTC.refreshTestResults();
+            }
+            catch (IllegalStateException e) {
+                /* Ignore the case where our message receiver has been
+                   disconnected. This happens when we leave the application
+                   before it finishes running all of the unit tests. */
+            }
+        }
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = 1;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = -1;
+                        break;
+                    default:
+                        RSTest_v14.log("Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            updateUI();
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/alloc.rs b/java/tests/RsTest_14/src/com/android/rs/test/alloc.rs
new file mode 100644
index 0000000..1b5e2ac
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/alloc.rs
@@ -0,0 +1,92 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int dimZ;
+
+rs_allocation aRaw;
+rs_allocation aFaces;
+rs_allocation aLOD;
+rs_allocation aFacesLOD;
+
+void root(int *o, uint32_t x, uint32_t y) {
+    *o = x + y * dimX;
+}
+
+static bool test_alloc_dims() {
+    bool failed = false;
+    int i, j;
+
+    _RS_ASSERT(rsAllocationGetDimX(aRaw) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aRaw) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aRaw) == dimZ);
+
+    // Test 2D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(aRaw, i, j);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    // Test 1D addressing
+    for (i = 0; i < dimX; i++) {
+        rsDebug("Verifying ", i);
+        const void *p = rsGetElementAt(aRaw, i);
+        int val = *(const int *)p;
+        _RS_ASSERT(val == i);
+    }
+
+    // Test 3D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(aRaw, i, j, 0);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    _RS_ASSERT(rsAllocationGetDimX(aFaces) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFaces) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFaces) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFaces) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFaces) == 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aLOD) == 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aLOD) != 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aFacesLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFacesLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFacesLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFacesLOD) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFacesLOD) != 0);
+
+    if (failed) {
+        rsDebug("test_alloc_dims FAILED", 0);
+    }
+    else {
+        rsDebug("test_alloc_dims PASSED", 0);
+    }
+
+    return failed;
+}
+
+void alloc_test() {
+    bool failed = false;
+    failed |= test_alloc_dims();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/foreach.rs b/java/tests/RsTest_14/src/com/android/rs/test/foreach.rs
new file mode 100644
index 0000000..3fa8f85
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/foreach.rs
@@ -0,0 +1,45 @@
+#include "shared.rsh"
+
+rs_allocation aRaw;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void foreach_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/fp_mad.rs b/java/tests/RsTest_14/src/com/android/rs/test/fp_mad.rs
new file mode 100644
index 0000000..b6f2b2a
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/fp_mad.rs
@@ -0,0 +1,174 @@
+#include "shared.rsh"
+
+const int TEST_COUNT = 1;
+
+static float data_f1[1025];
+static float4 data_f4[1025];
+
+static void test_mad4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 80); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = (data_f4[i] * 0.02f +
+                          data_f4[i+1] * 0.04f +
+                          data_f4[i+2] * 0.05f +
+                          data_f4[i+3] * 0.1f +
+                          data_f4[i+4] * 0.2f +
+                          data_f4[i+5] * 0.2f +
+                          data_f4[i+6] * 0.1f +
+                          data_f4[i+7] * 0.05f +
+                          data_f4[i+8] * 0.04f +
+                          data_f4[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad4 M ops", 1000.f / time);
+}
+
+static void test_mad(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 20); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = (data_f1[i] * 0.02f +
+                          data_f1[i+1] * 0.04f +
+                          data_f1[i+2] * 0.05f +
+                          data_f1[i+3] * 0.1f +
+                          data_f1[i+4] * 0.2f +
+                          data_f1[i+5] * 0.2f +
+                          data_f1[i+6] * 0.1f +
+                          data_f1[i+7] * 0.05f +
+                          data_f1[i+8] * 0.04f +
+                          data_f1[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad M ops", 1000.f / time);
+}
+
+static void test_norm(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = normalize(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_norm M ops", 10.f / time);
+}
+
+static void test_sincos4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10 / 4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos4 M ops", 10.f / time);
+}
+
+static void test_sincos(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos M ops", 10.f / time);
+}
+
+static void test_clamp(uint32_t index) {
+    start();
+
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = clamp(data_f1[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp M ops", 100.f / time);
+
+    start();
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            if (data_f1[i] < -1.f) data_f1[i] = -1.f;
+            if (data_f1[i] > -1.f) data_f1[i] = 1.f;
+        }
+    }
+
+    time = end(index);
+    rsDebug("fp_clamp ref M ops", 100.f / time);
+}
+
+static void test_clamp4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100 /4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = clamp(data_f4[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp4 M ops", 100.f / time);
+}
+
+void fp_mad_test(uint32_t index, int test_num) {
+    int x;
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f;
+        data_f4[x].x = (x & 0xf) * 0.1f;
+        data_f4[x].y = (x & 0xf0) * 0.1f;
+        data_f4[x].z = (x & 0x33) * 0.1f;
+        data_f4[x].w = (x & 0x77) * 0.1f;
+    }
+
+    test_mad4(index);
+    test_mad(index);
+
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].x = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].y = (x & 0xf0) * 0.1f + 1.f;
+        data_f4[x].z = (x & 0x33) * 0.1f + 1.f;
+        data_f4[x].w = (x & 0x77) * 0.1f + 1.f;
+    }
+
+    test_norm(index);
+    test_sincos4(index);
+    test_sincos(index);
+    test_clamp4(index);
+    test_clamp(index);
+
+    // TODO Actually verify test result accuracy
+    rsDebug("fp_mad_test PASSED", 0);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/math.rs b/java/tests/RsTest_14/src/com/android/rs/test/math.rs
new file mode 100644
index 0000000..e6b37f6
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/math.rs
@@ -0,0 +1,462 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define INIT_PREFIX_TYPE(prefix, type)  \
+prefix##_##type##_1 = 1;                \
+prefix##_##type##_2.x = 1;              \
+prefix##_##type##_2.y = 1;              \
+prefix##_##type##_3.x = 1;              \
+prefix##_##type##_3.y = 1;              \
+prefix##_##type##_3.z = 1;              \
+prefix##_##type##_4.x = 1;              \
+prefix##_##type##_4.y = 1;              \
+prefix##_##type##_4.z = 1;              \
+prefix##_##type##_4.w = 1;
+
+#define INIT_TYPE(type)         \
+INIT_PREFIX_TYPE(src1, type)    \
+INIT_PREFIX_TYPE(src2, type)    \
+INIT_PREFIX_TYPE(res, type)
+
+#define INIT_ALL    \
+INIT_TYPE(c);       \
+INIT_TYPE(uc);      \
+INIT_TYPE(s);       \
+INIT_TYPE(us);      \
+INIT_TYPE(i);       \
+INIT_TYPE(ui);
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    INIT_ALL;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_int_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/math.rs.bak b/java/tests/RsTest_14/src/com/android/rs/test/math.rs.bak
new file mode 100644
index 0000000..ad802ca
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/math.rs.bak
@@ -0,0 +1,423 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    rsDebug("Here ", 1);
+    res_uc_3 = src1_uc_3 / src2_uc_3;
+    rsDebug("Here ", 2);
+    failed |= test_basic_operators();
+    rsDebug("Here ", 3);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/math.rs.orig b/java/tests/RsTest_14/src/com/android/rs/test/math.rs.orig
new file mode 100644
index 0000000..aae29a4
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/math.rs.orig
@@ -0,0 +1,436 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_int_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/primitives.rs b/java/tests/RsTest_14/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..ce451da
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool test_primitive_types(uint32_t index) {
+    bool failed = false;
+    start();
+
+    _RS_ASSERT(floatTest == 2.99f);
+    _RS_ASSERT(doubleTest == 3.05);
+    _RS_ASSERT(charTest == -16);
+    _RS_ASSERT(shortTest == -32);
+    _RS_ASSERT(intTest == -64);
+    _RS_ASSERT(longTest == 17179869185l);
+    _RS_ASSERT(longlongTest == 68719476735l);
+
+    _RS_ASSERT(ucharTest == 8);
+    _RS_ASSERT(ushortTest == 16);
+    _RS_ASSERT(uintTest == 32);
+    _RS_ASSERT(ulongTest == 4611686018427387903L);
+    _RS_ASSERT(int64_tTest == -17179869184l);
+    _RS_ASSERT(uint64_tTest == 117179869185l);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_primitives FAILED", time);
+    }
+    else {
+        rsDebug("test_primitives PASSED", time);
+    }
+
+    return failed;
+}
+
+void primitives_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_primitive_types(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/refcount.rs b/java/tests/RsTest_14/src/com/android/rs/test/refcount.rs
new file mode 100644
index 0000000..4ea70e2
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/refcount.rs
@@ -0,0 +1,13 @@
+#include "shared.rsh"
+
+// Testing reference counting of RS object types
+
+rs_allocation globalA;
+static rs_allocation staticGlobalA;
+
+void refcount_test() {
+    staticGlobalA = globalA;
+    rsClearObject(&globalA);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/rsdebug.rs b/java/tests/RsTest_14/src/com/android/rs/test/rsdebug.rs
new file mode 100644
index 0000000..f7942a5
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/rsdebug.rs
@@ -0,0 +1,56 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    // For this reason, none of the outputs are actually checked.
+
+    rsDebug("floatTest", floatTest);
+    rsDebug("doubleTest", doubleTest);
+    rsDebug("charTest", charTest);
+    rsDebug("shortTest", shortTest);
+    rsDebug("intTest", intTest);
+    rsDebug("longTest", longTest);
+    rsDebug("longlongTest", longlongTest);
+
+    rsDebug("ucharTest", ucharTest);
+    rsDebug("ushortTest", ushortTest);
+    rsDebug("uintTest", uintTest);
+    rsDebug("ulongTest", ulongTest);
+    rsDebug("int64_tTest", int64_tTest);
+    rsDebug("uint64_tTest", uint64_tTest);
+
+    return failed;
+}
+
+void test_rsdebug(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rsdebug_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rsdebug_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/rslist.rs b/java/tests/RsTest_14/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..b3d8b9e
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,107 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_v14)
+
+#include "rs_graphics.rsh"
+
+float gDY;
+
+rs_font gFont;
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
+void init() {
+    gDY = 0.0f;
+}
+
+int textPos = 0;
+
+int root(void) {
+
+    rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    rsgClearDepth(1.0f);
+
+    textPos -= (int)gDY*2;
+    gDY *= 0.95;
+
+    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+    rsgBindFont(gFont);
+
+    rs_allocation listAlloc;
+    listAlloc = rsGetAllocation(gList);
+    int allocSize = rsAllocationGetDimX(listAlloc);
+
+    int width = rsgGetWidth();
+    int height = rsgGetHeight();
+
+    int itemHeight = 80;
+    int totalItemHeight = itemHeight * allocSize;
+
+    /* Prevent scrolling above the top of the list */
+    int firstItem = height - totalItemHeight;
+    if (firstItem < 0) {
+        firstItem = 0;
+    }
+
+    /* Prevent scrolling past the last line of the list */
+    int lastItem = -1 * (totalItemHeight - height);
+    if (lastItem > 0) {
+        lastItem = 0;
+    }
+
+    if (textPos > firstItem) {
+        textPos = firstItem;
+    }
+    else if (textPos < lastItem) {
+        textPos = lastItem;
+    }
+
+    int currentYPos = itemHeight + textPos;
+
+    for(int i = 0; i < allocSize; i ++) {
+        if(currentYPos - itemHeight > height) {
+            break;
+        }
+
+        if(currentYPos > 0) {
+            switch(gList[i].result) {
+                case 1: /* Passed */
+                    rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f);
+                    break;
+                case -1: /* Failed */
+                    rsgFontColor(0.9f, 0.5f, 0.5f, 1.0f);
+                    break;
+                case 0: /* Still Testing */
+                    rsgFontColor(0.9f, 0.9f, 0.5f, 1.0f);
+                    break;
+                default: /* Unknown */
+                    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+                    break;
+            }
+            rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0);
+            rsgDrawText(gList[i].text, 30, currentYPos - 32);
+        }
+        currentYPos += itemHeight;
+    }
+
+    return 10;
+}
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/rstime.rs b/java/tests/RsTest_14/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..5e3e078
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (only valid for PST localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/rstypes.rs b/java/tests/RsTest_14/src/com/android/rs/test/rstypes.rs
new file mode 100644
index 0000000..22d9c13
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/rstypes.rs
@@ -0,0 +1,79 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element elementTest;
+rs_type typeTest;
+rs_allocation allocationTest;
+rs_sampler samplerTest;
+rs_script scriptTest;
+rs_mesh meshTest;
+rs_program_fragment program_fragmentTest;
+rs_program_vertex program_vertexTest;
+rs_program_raster program_rasterTest;
+rs_program_store program_storeTest;
+rs_font fontTest;
+
+rs_matrix4x4 matrix4x4Test;
+rs_matrix3x3 matrix3x3Test;
+rs_matrix2x2 matrix2x2Test;
+
+struct my_struct {
+    int i;
+    rs_font fontTestStruct;
+};
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_matrix4x4 matrix4x4TestLocal;
+    rs_matrix3x3 matrix3x3TestLocal;
+    rs_matrix2x2 matrix2x2TestLocal;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    rs_element elementTestLocal;
+    rs_type typeTestLocal;
+    rs_allocation allocationTestLocal;
+    rs_sampler samplerTestLocal;
+    rs_script scriptTestLocal;
+    rs_mesh meshTestLocal;
+    rs_program_fragment program_fragmentTestLocal;
+    rs_program_vertex program_vertexTestLocal;
+    rs_program_raster program_rasterTestLocal;
+    rs_program_store program_storeTestLocal;
+    rs_font fontTestLocal;
+
+    rs_font fontTestLocalArray[4];
+
+    rs_font fontTestLocalPreInit = fontTest;
+
+    struct my_struct structTest;
+
+    fontTestLocal = fontTest;
+    //allocationTestLocal = allocationTest;
+
+    fontTest = fontTestLocal;
+    //allocationTest = allocationTestLocal;
+
+    /*for (int i = 0; i < 4; i++) {
+        fontTestLocalArray[i] = fontTestLocal;
+    }*/
+
+    /*fontTest = fontTestLocalArray[3];*/
+
+    return failed;
+}
+
+void test_rstypes(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstypes_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstypes_test PASSED", 0);
+    }
+}
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/shared.rsh b/java/tests/RsTest_14/src/com/android/rs/test/shared.rsh
new file mode 100644
index 0000000..4a7151f
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/shared.rsh
@@ -0,0 +1,38 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_v14)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/test_root.rs b/java/tests/RsTest_14/src/com/android/rs/test/test_root.rs
new file mode 100644
index 0000000..88fe34a
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/test_root.rs
@@ -0,0 +1,23 @@
+// Fountain test script
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_v14)
+
+#pragma stateFragment(parent)
+
+#include "rs_graphics.rsh"
+
+
+typedef struct TestResult {
+    rs_allocation name;
+    bool pass;
+    float score;
+} TestResult_t;
+TestResult_t *results;
+
+int root() {
+
+    return 0;
+}
+
+
diff --git a/java/tests/RsTest_14/src/com/android/rs/test/vector.rs b/java/tests/RsTest_14/src/com/android/rs/test/vector.rs
new file mode 100644
index 0000000..0430a2f
--- /dev/null
+++ b/java/tests/RsTest_14/src/com/android/rs/test/vector.rs
@@ -0,0 +1,198 @@
+#include "shared.rsh"
+
+// Testing vector types
+float2 f2 = { 1.0f, 2.0f };
+float3 f3 = { 1.0f, 2.0f, 3.0f };
+float4 f4 = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+double2 d2 = { 1.0, 2.0 };
+double3 d3 = { 1.0, 2.0, 3.0 };
+double4 d4 = { 1.0, 2.0, 3.0, 4.0 };
+
+char2 i8_2 = { 1, 2 };
+char3 i8_3 = { 1, 2, 3 };
+char4 i8_4 = { 1, 2, 3, 4 };
+
+uchar2 u8_2 = { 1, 2 };
+uchar3 u8_3 = { 1, 2, 3 };
+uchar4 u8_4 = { 1, 2, 3, 4 };
+
+short2 i16_2 = { 1, 2 };
+short3 i16_3 = { 1, 2, 3 };
+short4 i16_4 = { 1, 2, 3, 4 };
+
+ushort2 u16_2 = { 1, 2 };
+ushort3 u16_3 = { 1, 2, 3 };
+ushort4 u16_4 = { 1, 2, 3, 4 };
+
+int2 i32_2 = { 1, 2 };
+int3 i32_3 = { 1, 2, 3 };
+int4 i32_4 = { 1, 2, 3, 4 };
+
+uint2 u32_2 = { 1, 2 };
+uint3 u32_3 = { 1, 2, 3 };
+uint4 u32_4 = { 1, 2, 3, 4 };
+
+long2 i64_2 = { 1, 2 };
+long3 i64_3 = { 1, 2, 3 };
+long4 i64_4 = { 1, 2, 3, 4 };
+
+ulong2 u64_2 = { 1, 2 };
+ulong3 u64_3 = { 1, 2, 3 };
+ulong4 u64_4 = { 1, 2, 3, 4 };
+
+static bool test_vector_types() {
+    bool failed = false;
+
+    rsDebug("Testing F32", 0);
+    _RS_ASSERT(f2.x == 2.99f);
+    _RS_ASSERT(f2.y == 3.99f);
+
+    _RS_ASSERT(f3.x == 2.99f);
+    _RS_ASSERT(f3.y == 3.99f);
+    _RS_ASSERT(f3.z == 4.99f);
+
+    _RS_ASSERT(f4.x == 2.99f);
+    _RS_ASSERT(f4.y == 3.99f);
+    _RS_ASSERT(f4.z == 4.99f);
+    _RS_ASSERT(f4.w == 5.99f);
+
+    rsDebug("Testing F64", 0);
+    _RS_ASSERT(d2.x == 2.99);
+    _RS_ASSERT(d2.y == 3.99);
+
+    _RS_ASSERT(d3.x == 2.99);
+    _RS_ASSERT(d3.y == 3.99);
+    _RS_ASSERT(d3.z == 4.99);
+
+    _RS_ASSERT(d4.x == 2.99);
+    _RS_ASSERT(d4.y == 3.99);
+    _RS_ASSERT(d4.z == 4.99);
+    _RS_ASSERT(d4.w == 5.99);
+
+    rsDebug("Testing I8", 0);
+    _RS_ASSERT(i8_2.x == 2);
+    _RS_ASSERT(i8_2.y == 3);
+
+    _RS_ASSERT(i8_3.x == 2);
+    _RS_ASSERT(i8_3.y == 3);
+    _RS_ASSERT(i8_3.z == 4);
+
+    _RS_ASSERT(i8_4.x == 2);
+    _RS_ASSERT(i8_4.y == 3);
+    _RS_ASSERT(i8_4.z == 4);
+    _RS_ASSERT(i8_4.w == 5);
+
+    rsDebug("Testing U8", 0);
+    _RS_ASSERT(u8_2.x == 2);
+    _RS_ASSERT(u8_2.y == 3);
+
+    _RS_ASSERT(u8_3.x == 2);
+    _RS_ASSERT(u8_3.y == 3);
+    _RS_ASSERT(u8_3.z == 4);
+
+    _RS_ASSERT(u8_4.x == 2);
+    _RS_ASSERT(u8_4.y == 3);
+    _RS_ASSERT(u8_4.z == 4);
+    _RS_ASSERT(u8_4.w == 5);
+
+    rsDebug("Testing I16", 0);
+    _RS_ASSERT(i16_2.x == 2);
+    _RS_ASSERT(i16_2.y == 3);
+
+    _RS_ASSERT(i16_3.x == 2);
+    _RS_ASSERT(i16_3.y == 3);
+    _RS_ASSERT(i16_3.z == 4);
+
+    _RS_ASSERT(i16_4.x == 2);
+    _RS_ASSERT(i16_4.y == 3);
+    _RS_ASSERT(i16_4.z == 4);
+    _RS_ASSERT(i16_4.w == 5);
+
+    rsDebug("Testing U16", 0);
+    _RS_ASSERT(u16_2.x == 2);
+    _RS_ASSERT(u16_2.y == 3);
+
+    _RS_ASSERT(u16_3.x == 2);
+    _RS_ASSERT(u16_3.y == 3);
+    _RS_ASSERT(u16_3.z == 4);
+
+    _RS_ASSERT(u16_4.x == 2);
+    _RS_ASSERT(u16_4.y == 3);
+    _RS_ASSERT(u16_4.z == 4);
+    _RS_ASSERT(u16_4.w == 5);
+
+    rsDebug("Testing I32", 0);
+    _RS_ASSERT(i32_2.x == 2);
+    _RS_ASSERT(i32_2.y == 3);
+
+    _RS_ASSERT(i32_3.x == 2);
+    _RS_ASSERT(i32_3.y == 3);
+    _RS_ASSERT(i32_3.z == 4);
+
+    _RS_ASSERT(i32_4.x == 2);
+    _RS_ASSERT(i32_4.y == 3);
+    _RS_ASSERT(i32_4.z == 4);
+    _RS_ASSERT(i32_4.w == 5);
+
+    rsDebug("Testing U32", 0);
+    _RS_ASSERT(u32_2.x == 2);
+    _RS_ASSERT(u32_2.y == 3);
+
+    _RS_ASSERT(u32_3.x == 2);
+    _RS_ASSERT(u32_3.y == 3);
+    _RS_ASSERT(u32_3.z == 4);
+
+    _RS_ASSERT(u32_4.x == 2);
+    _RS_ASSERT(u32_4.y == 3);
+    _RS_ASSERT(u32_4.z == 4);
+    _RS_ASSERT(u32_4.w == 5);
+
+    rsDebug("Testing I64", 0);
+    _RS_ASSERT(i64_2.x == 2);
+    _RS_ASSERT(i64_2.y == 3);
+
+    _RS_ASSERT(i64_3.x == 2);
+    _RS_ASSERT(i64_3.y == 3);
+    _RS_ASSERT(i64_3.z == 4);
+
+    _RS_ASSERT(i64_4.x == 2);
+    _RS_ASSERT(i64_4.y == 3);
+    _RS_ASSERT(i64_4.z == 4);
+    _RS_ASSERT(i64_4.w == 5);
+
+    rsDebug("Testing U64", 0);
+    _RS_ASSERT(u64_2.x == 2);
+    _RS_ASSERT(u64_2.y == 3);
+
+    _RS_ASSERT(u64_3.x == 2);
+    _RS_ASSERT(u64_3.y == 3);
+    _RS_ASSERT(u64_3.z == 4);
+
+    _RS_ASSERT(u64_4.x == 2);
+    _RS_ASSERT(u64_4.y == 3);
+    _RS_ASSERT(u64_4.z == 4);
+    _RS_ASSERT(u64_4.w == 5);
+
+    if (failed) {
+        rsDebug("test_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void vector_test() {
+    bool failed = false;
+    failed |= test_vector_types();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/java/tests/SampleTest/Android.mk b/java/tests/SampleTest/Android.mk
new file mode 100644
index 0000000..f3439b0
--- /dev/null
+++ b/java/tests/SampleTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := SampleRS
+
+include $(BUILD_PACKAGE)
diff --git a/java/tests/SampleTest/AndroidManifest.xml b/java/tests/SampleTest/AndroidManifest.xml
new file mode 100644
index 0000000..ec115f7
--- /dev/null
+++ b/java/tests/SampleTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.sample">
+    <uses-sdk android:minSdkVersion="14" />
+    <application android:label="Sample Test"
+                 android:hardwareAccelerated="true">
+
+        <activity android:name="SampleRSActivity"
+                  android:label="Sample Test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/tests/SampleTest/res/drawable-nodpi/city.png b/java/tests/SampleTest/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..27c4618
--- /dev/null
+++ b/java/tests/SampleTest/res/drawable-nodpi/city.png
Binary files differ
diff --git a/java/tests/SampleTest/res/drawable-nodpi/twobytwo.png b/java/tests/SampleTest/res/drawable-nodpi/twobytwo.png
new file mode 100644
index 0000000..98cf963
--- /dev/null
+++ b/java/tests/SampleTest/res/drawable-nodpi/twobytwo.png
Binary files differ
diff --git a/java/tests/SampleTest/res/layout/rs.xml b/java/tests/SampleTest/res/layout/rs.xml
new file mode 100644
index 0000000..f2a356f
--- /dev/null
+++ b/java/tests/SampleTest/res/layout/rs.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/wraplinear"/>
+            <TextureView
+                android:id="@+id/display"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/clamplinear"/>
+            <TextureView
+                android:id="@+id/display2"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/wrapnearest"/>
+            <TextureView
+                android:id="@+id/display3"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/clampnearest"/>
+            <TextureView
+                android:id="@+id/display4"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/benchmark"/>
+            </LinearLayout>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/java/tests/SampleTest/res/values/strings.xml b/java/tests/SampleTest/res/values/strings.xml
new file mode 100644
index 0000000..a0a2499
--- /dev/null
+++ b/java/tests/SampleTest/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <string name="benchmark">Benchmark</string>
+    <string name="wraplinear">Wrap Linear</string>
+    <string name="clamplinear">Clamp Linear</string>
+    <string name="wrapnearest">Wrap Nearest</string>
+    <string name="clampnearest">Clamp Nearest</string>
+</resources>
diff --git a/java/tests/SampleTest/src/com/android/rs/sample/SampleRSActivity.java b/java/tests/SampleTest/src/com/android/rs/sample/SampleRSActivity.java
new file mode 100644
index 0000000..77cbf84
--- /dev/null
+++ b/java/tests/SampleTest/src/com/android/rs/sample/SampleRSActivity.java
@@ -0,0 +1,169 @@
+/*
+ * 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 com.android.rs.sample;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix3f;
+import android.renderscript.RenderScript;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.renderscript.Type.Builder;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.TextureView.SurfaceTextureListener;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class SampleRSActivity extends Activity {
+    class TextureViewUpdater implements TextureView.SurfaceTextureListener {
+        private Allocation mOutPixelsAllocation;
+        private Sampler mSampler;
+
+        TextureViewUpdater(Allocation outAlloc, Sampler sampler) {
+            mOutPixelsAllocation = outAlloc;
+            mSampler = sampler;
+        }
+
+        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        }
+
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+            mOutPixelsAllocation.setSurfaceTexture(surface);
+        }
+
+        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+            mOutPixelsAllocation.setSurfaceTexture(surface);
+            filterAlloc(mOutPixelsAllocation, mSampler);
+        }
+
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+            mOutPixelsAllocation.setSurfaceTexture(null);
+            return true;
+        }
+    }
+
+    private final String TAG = "Img";
+    private Bitmap mBitmapTwoByTwo;
+    private Bitmap mBitmapCity;
+
+    private TextView mBenchmarkResult;
+
+    private RenderScript mRS;
+    private Allocation mTwoByTwoAlloc;
+    private Allocation mCityAlloc;
+    private ScriptC_sample mScript;
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.rs);
+
+        mBitmapTwoByTwo = loadBitmap(R.drawable.twobytwo);
+        mBitmapCity = loadBitmap(R.drawable.city);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+        mRS = RenderScript.create(this);
+        mTwoByTwoAlloc = Allocation.createFromBitmap(mRS, mBitmapTwoByTwo,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+
+        mCityAlloc = Allocation.createFromBitmap(mRS, mBitmapCity,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+
+        Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+
+        int usage = Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT;
+
+        int outX = 256;
+        int outY = 256;
+
+        // Wrap Linear
+        Allocation outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        TextureViewUpdater updater = new TextureViewUpdater(outAlloc, Sampler.WRAP_LINEAR(mRS));
+        TextureView displayView = (TextureView) findViewById(R.id.display);
+        displayView.setSurfaceTextureListener(updater);
+
+        // Clamp Linear
+        outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        updater = new TextureViewUpdater(outAlloc, Sampler.CLAMP_LINEAR(mRS));
+        displayView = (TextureView) findViewById(R.id.display2);
+        displayView.setSurfaceTextureListener(updater);
+
+        // Wrap Nearest
+        outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        updater = new TextureViewUpdater(outAlloc, Sampler.WRAP_NEAREST(mRS));
+        displayView = (TextureView) findViewById(R.id.display3);
+        displayView.setSurfaceTextureListener(updater);
+
+        // Clamp Nearest
+        outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        updater = new TextureViewUpdater(outAlloc, Sampler.CLAMP_NEAREST(mRS));
+        displayView = (TextureView) findViewById(R.id.display4);
+        displayView.setSurfaceTextureListener(updater);
+
+        mScript = new ScriptC_sample(mRS, getResources(), R.raw.sample);
+    }
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
+        Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
+        Canvas c = new Canvas(b2);
+        c.drawBitmap(b, 0, 0, null);
+        b.recycle();
+        return b2;
+    }
+
+    private synchronized void filterAlloc(Allocation alloc, Sampler sampler) {
+        long t = java.lang.System.currentTimeMillis();
+        mScript.invoke_setSampleData(alloc, mTwoByTwoAlloc, sampler);
+        mScript.forEach_root(alloc);
+        alloc.ioSendOutput();
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        Log.i(TAG, "Filter time is: " + t + " ms");
+    }
+
+    public void benchmark(View v) {
+        /*filterAlloc();
+        long t = java.lang.System.currentTimeMillis();
+        filterAlloc();
+        t = java.lang.System.currentTimeMillis() - t;
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: " + t + " ms");*/
+    }
+}
diff --git a/java/tests/SampleTest/src/com/android/rs/sample/sample.rs b/java/tests/SampleTest/src/com/android/rs/sample/sample.rs
new file mode 100644
index 0000000..e2bf43d
--- /dev/null
+++ b/java/tests/SampleTest/src/com/android/rs/sample/sample.rs
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.sample)
+#include "rs_graphics.rsh"
+
+static rs_allocation sourceAlloc;
+static rs_allocation destAlloc;
+static rs_sampler allocSampler;
+
+void setSampleData(rs_allocation dest, rs_allocation source, rs_sampler sampler) {
+    destAlloc = dest;
+    sourceAlloc = source;
+    allocSampler = sampler;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+
+    float destX = (float)rsAllocationGetDimX(destAlloc) - 1.0f;
+    float destY = (float)rsAllocationGetDimY(destAlloc) - 1.0f;
+
+    float2 uv;
+    uv.x = (float)x / destX;
+    uv.y = (float)y / destY;
+
+    out->xyz = convert_uchar3(rsSample(sourceAlloc, allocSampler, uv*2.0f).xyz);
+    out->w = 0xff;
+}
+