Fix RS bug with message ID 0.

Clamp RSTest list to nice viewable range.

Change-Id: I0909511e16984ec78150cda17c22e22af1fa0cdb
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2aa3e84..c4421c3 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -601,9 +601,9 @@
             while(mRun) {
                 rbuf[0] = 0;
                 int msg = mRS.nContextGetMessage(mRS.mContext, rbuf, true);
-                if ((msg == 0) && mRun) {
+                if ((msg == 0)) {
                     // Can happen for two reasons
-                    if (rbuf[0] > 0) {
+                    if (rbuf[0] > 0 && mRun) {
                         // 1: Buffer needs to be enlarged.
                         rbuf = new int[rbuf[0] + 2];
                     } else {
@@ -616,6 +616,7 @@
                         } catch(InterruptedException e) {
                         }
                     }
+                    continue;
                 }
                 if(mRS.mMessageCallback != null) {
                     mRS.mMessageCallback.mData = rbuf;
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index cd8f814..dbc9133 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -40,6 +40,8 @@
     private ScriptC_rslist mScript;
 
     private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
 
     public void init(RenderScriptGL rs, Resources res, int width, int height) {
         mRS = rs;
@@ -54,9 +56,13 @@
         unitTests.add(new UT_primitives(this, mRes));
         unitTests.add(new UT_fp_mad(this, mRes));
         /*
-        unitTests.add(new UnitTest("<Pass>", 1));
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
         unitTests.add(new UnitTest());
-        unitTests.add(new UnitTest("<Fail>", -1));
+        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()];
@@ -71,19 +77,6 @@
             uta[i].setItem(listElem);
         }
 
-        /* Run the actual unit tests */
-        ListIterator<UnitTest> test_iter = unitTests.listIterator();
-        while (test_iter.hasNext()) {
-            UnitTest t = test_iter.next();
-            t.start();
-            /*
-            try {
-                t.join();
-            } catch (InterruptedException e) {
-            }
-            */
-        }
-
         mListAllocs.copyAll();
 
         mScript.bind_gList(mListAllocs);
@@ -92,10 +85,40 @@
         mScript.set_gFont(mFont);
 
         mRS.contextBindRootScript(mScript);
-        mRS.finish();
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+    }
+
+    static int count = 0;
+    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 (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. */
+            }
+        }
+        count++;
     }
 
     public void refreshTestResults() {
+        checkAndRunNextTest();
+
         if (mListAllocs != null && mScript != null && mRS != null) {
             mListAllocs.copyAll();
 
@@ -111,6 +134,7 @@
         mScript.set_gDY(0.0f);
         mLastX = x;
         mLastY = y;
+        refreshTestResults();
     }
 
     public void onActionMove(int x, int y) {
@@ -125,5 +149,6 @@
 
         mLastX = x;
         mLastY = y;
+        refreshTestResults();
     }
 }
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
index d98b763..5eb0d67 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
@@ -16,6 +16,7 @@
 
 package com.android.rs.test;
 import android.renderscript.RenderScript.RSMessage;
+import android.util.Log;
 
 public class UnitTest extends Thread {
     public String name;
@@ -27,11 +28,15 @@
     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) {
         super();
         mRSTC = rstc;
         name = n;
         result = initResult;
+        testID = numTests++;
     }
 
     protected UnitTest(RSTestCore rstc, String n) {
@@ -56,12 +61,20 @@
                     result = -1;
                     break;
                 default:
-                    break;
+                    android.util.Log.v("RenderScript", "Unit test got unexpected message");
+                    return;
             }
 
             if (mItem != null) {
                 mItem.result = result;
-                mRSTC.refreshTestResults();
+                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. */
+                }
             }
         }
     };
@@ -72,6 +85,9 @@
 
     public void run() {
         /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
     }
 }
 
diff --git a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
index eb82e56..dfd77e6 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
@@ -170,7 +170,7 @@
 
     // TODO Actually verify test result accuracy
     rsDebug("fp_mad_test PASSED", 0);
-    rsSendToClient(RS_MSG_TEST_PASSED);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
 }
 
 
diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
index 2ba5d52..5312bcc 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
@@ -42,10 +42,10 @@
     failed |= test_primitive_types(index);
 
     if (failed) {
-        rsSendToClient(RS_MSG_TEST_FAILED);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
     }
     else {
-        rsSendToClient(RS_MSG_TEST_PASSED);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
     }
 }
 
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
index 72d1850..a5f0f6b 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
@@ -56,6 +56,27 @@
     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 ++) {