- Add instrumentation utility to automate rs performance tests:
  The RsBench test activity can be launched within instrumentation

- Provide parameter to control test run:
  set the maximum number of loops from test runner,
  the script will send out a message after the test loops exceeds the maxium number

Change-Id: I5fba0543094ef7a8b5eaa6ff9a04367d272b4d65
diff --git a/tests/RenderScriptTests/PerfTest/Android.mk b/tests/RenderScriptTests/PerfTest/Android.mk
index 85b0a65..757b3b1 100644
--- a/tests/RenderScriptTests/PerfTest/Android.mk
+++ b/tests/RenderScriptTests/PerfTest/Android.mk
@@ -19,7 +19,9 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+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
diff --git a/tests/RenderScriptTests/PerfTest/AndroidManifest.xml b/tests/RenderScriptTests/PerfTest/AndroidManifest.xml
index 3afb3b2..e024882 100644
--- a/tests/RenderScriptTests/PerfTest/AndroidManifest.xml
+++ b/tests/RenderScriptTests/PerfTest/AndroidManifest.xml
@@ -3,7 +3,8 @@
     package="com.android.perftest">
     <uses-sdk android:minSdkVersion="11" />
     <application android:label="PerfTest"
-    android:icon="@drawable/test_pattern">
+      android:icon="@drawable/test_pattern">
+        <uses-library android:name="android.test.runner" />
         <activity android:name="RsBench"
                   android:label="RsBenchmark"
                   android:theme="@android:style/Theme.Black.NoTitleBar">
@@ -12,5 +13,10 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-    </application>
+      </application>
+
+      <instrumentation android:name=".RsPerfTestRunner"
+        android:targetPackage="com.android.perftest"
+        android:label="Test runner for RsBench tests"
+      />
 </manifest>
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
index 11ad11a..d7393f8 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
@@ -21,6 +21,8 @@
 
 import android.app.Activity;
 import android.content.res.Configuration;
+import android.content.Intent;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -37,17 +39,27 @@
 import java.lang.Runtime;
 
 public class RsBench extends Activity {
-
-    private RsBenchView mView;
+    private final String TAG = "RsBench";
+    public RsBenchView mView;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-
+        int iterations = 0;
+        Intent intent = getIntent();
+        Uri uri = intent.getData();
+        if (uri != null) {
+            // when lauched from instrumentation
+            String scheme = uri.getScheme();
+            if ("iterations".equals(scheme)) {
+                iterations = Integer.parseInt(uri.getSchemeSpecificPart());
+            }
+        }
         // Create our Preview view and set it as the content of our
         // Activity
         mView = new RsBenchView(this);
         setContentView(mView);
+        mView.setLoops(iterations);
     }
 
     @Override
@@ -65,6 +77,4 @@
         super.onPause();
         mView.pause();
     }
-
 }
-
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index 5443ef8..4d4adf6 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -29,6 +29,7 @@
 import android.renderscript.ProgramStore.DepthFunc;
 import android.renderscript.ProgramStore.BlendSrcFunc;
 import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.RenderScript.RSMessageHandler;
 import android.renderscript.Sampler.Value;
 import android.util.Log;
 
@@ -37,11 +38,12 @@
 
     int mWidth;
     int mHeight;
+    int mLoops;
 
     public RsBenchRS() {
     }
 
-    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+    public void init(RenderScriptGL rs, Resources res, int width, int height, int loops) {
         mRS = rs;
         mRes = res;
         mWidth = width;
@@ -50,9 +52,12 @@
         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
         mMode = 0;
         mMaxModes = 0;
+        mLoops = loops;
         initRS();
     }
 
+    private boolean stopTest = false;
+
     private Resources mRes;
     private RenderScriptGL mRS;
 
@@ -121,6 +126,43 @@
         mScript.set_gDisplayMode(mMode);
     }
 
+    /**
+     * Create a message handler to handle message sent from the script
+     */
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (mID == mScript.get_RS_MSG_TEST_DONE()) {
+                synchronized(this) {
+                    stopTest = true;
+                    this.notifyAll();
+                }
+                return;
+            } else {
+                Log.v("RsBenchRS", "Perf test got unexpected message");
+                return;
+            }
+        }
+    };
+
+    /**
+     * Wait for message from the script
+     */
+    public boolean testIsFinished() {
+        synchronized(this) {
+            while (true) {
+                if (stopTest) {
+                    return true;
+                } else {
+                    try {
+                        this.wait(60*1000);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
     ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
         ProgramStore.Builder builder = new ProgramStore.Builder(rs);
         builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
@@ -388,8 +430,10 @@
     private void initRS() {
 
         mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
+        mRS.setMessageHandler(mRsMessage);
 
         mMaxModes = mScript.get_gMaxModes();
+        mScript.set_gMaxLoops(mLoops);
 
         initSamplers();
         initProgramStore();
@@ -421,6 +465,3 @@
         mRS.bindRootScript(mScript);
     }
 }
-
-
-
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchTest.java
new file mode 100644
index 0000000..199200b
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.perftest;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+/**
+ * To run the test, please use command
+ *
+ * adb shell am instrument -w com.android.perftest/.RsPerfTestRunner
+ *
+ */
+public class RsBenchTest extends ActivityInstrumentationTestCase2<RsBench> {
+    private String TAG = "RsBenchTest";
+    private int iterations = 0;
+    private RsBench mAct;
+
+    public RsBenchTest() {
+        super(RsBench.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        Instrumentation mInst = getInstrumentation();
+        RsPerfTestRunner mRunner = (RsPerfTestRunner) getInstrumentation();
+        iterations = mRunner.iterations;
+        Log.v(TAG, "Run benchmark for " + iterations + " iterations.");
+
+        Uri data = Uri.fromParts("iterations", Integer.toString(iterations), null);
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setClassName("com.android.perftest", "com.android.perftest.RsBench");
+        intent.setData(data);
+        mAct = (RsBench) mInst.startActivitySync(intent);
+        mInst.waitForIdleSync();
+
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mAct.finish();
+        super.tearDown();
+    }
+
+    /**
+     * Run tests and wait until the test has been run for iterations.
+     */
+    @LargeTest
+    public void testRsBench() {
+        if (mAct.mView.testIsFinished()) {
+            return;
+        } else {
+            fail("test didn't stop correctly");
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
index ee7e508..2882b93 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
@@ -23,6 +23,7 @@
 import android.renderscript.RSSurfaceView;
 import android.renderscript.RenderScript;
 import android.renderscript.RenderScriptGL;
+import android.renderscript.RenderScript.RSMessageHandler;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -47,7 +48,7 @@
 
     private RenderScriptGL mRS;
     private RsBenchRS mRender;
-
+    private int mLoops = 0;
 
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         super.surfaceChanged(holder, format, w, h);
@@ -57,7 +58,8 @@
             mRS = createRenderScriptGL(sc);
             mRS.setSurface(holder, w, h);
             mRender = new RsBenchRS();
-            mRender.init(mRS, getResources(), w, h);
+            Log.v("RsBenchView", "mLoops = " + mLoops);
+            mRender.init(mRS, getResources(), w, h, mLoops);
         }
     }
 
@@ -86,6 +88,21 @@
 
         return ret;
     }
+
+    /**
+     * Set the total number of loops the benchmark tests will run
+     * before the test results are collected.
+     */
+    public void setLoops(int iterations) {
+        if (iterations > 0) {
+            mLoops = iterations;
+        }
+    }
+
+    /**
+     * Wait for message from the script
+     */
+    public boolean testIsFinished() {
+        return mRender.testIsFinished();
+    }
 }
-
-
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsPerfTestRunner.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsPerfTestRunner.java
new file mode 100644
index 0000000..031af6a08
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsPerfTestRunner.java
@@ -0,0 +1,56 @@
+/*
+ * 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.perftest;
+
+//import com.android.perftest.RsBenchTest;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+import junit.framework.TestSuite;
+
+/**
+ * Run the RenderScript Performance Test
+ * adb shell am instrument -w com.android.perftest/.RsPerfTestRunner
+ *
+ * with specified iterations:
+ * adb shell am instrument -e iterations <n> -w com.android.perftest/.RsPerfTestRunner
+ *
+ */
+public class RsPerfTestRunner extends InstrumentationTestRunner {
+    public int iterations = 10;
+
+    @Override
+    public TestSuite getAllTests() {
+        TestSuite suite = new InstrumentationTestSuite(this);
+        suite.addTestSuite(RsBenchTest.class);
+        return suite;
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        String strValue = (String)icicle.get("iterations");
+        if (strValue != null) {
+            int intValue = Integer.parseInt(strValue);
+            if (iterations > 0) {
+                iterations = intValue;
+            }
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index fd0f16f..a663d35 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -19,7 +19,11 @@
 #include "rs_graphics.rsh"
 #include "shader_def.rsh"
 
+/* Message sent from script to renderscript */
+const int RS_MSG_TEST_DONE = 100;
+
 const int gMaxModes = 26;
+int gMaxLoops;
 
 rs_program_vertex gProgVertex;
 rs_program_fragment gProgFragmentColor;
@@ -634,6 +638,8 @@
 }
 
 static int benchMode = 0;
+static int runningLoops = 0;
+static bool sendMsgFlag = false;
 
 static const char *testNames[] = {
     "Finished text fill 1,",
@@ -828,7 +834,13 @@
 
     if (benchMode > gMaxModes) {
         benchMode = 0;
+        runningLoops++;
+        if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) {
+            //Notifiy the test to stop and get results
+            rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops);
+            rsSendToClientBlocking(RS_MSG_TEST_DONE);
+            sendMsgFlag = true;
+        }
     }
-
     return 1;
 }