Implement OOB destroy method that can be called from the java finalizer removing the need to explicitly destroy objects.
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index eaeb401..c25f16a 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -60,8 +60,13 @@
     protected void finalize() throws Throwable
     {
         if (!mDestroyed) {
+            if(mID != 0) {
+                mRS.nObjDestroyOOB(mID);
+            }
+            mID = 0;
+            mDestroyed = true;
             Log.v(RenderScript.LOG_TAG,
-                  getClass() + " finalized without having released the RS reference.");
+                  getClass() + " auto finalizing object without having released the RS reference.");
         }
         super.finalize();
     }
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 08418c6..fca1c7a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -75,6 +75,7 @@
 
     native void nAssignName(int obj, byte[] name);
     native void nObjDestroy(int id);
+    native void nObjDestroyOOB(int id);
     native int  nFileOpen(byte[] name);
 
     native void nElementBegin();
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 2d48165..001ecd0 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -86,6 +86,15 @@
     rsObjDestroy(con, (void *)obj);
 }
 
+static void
+nObjDestroyOOB(JNIEnv *_env, jobject _this, jint obj)
+{
+    // This function only differs from nObjDestroy in that it calls the
+    // special Out Of Band version of ObjDestroy which is thread safe.
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nObjDestroyOOB, con(%p) obj(%p)", con, (void *)obj);
+    rsObjDestroyOOB(con, (void *)obj);
+}
 
 static jint
 nFileOpen(JNIEnv *_env, jobject _this, jbyteArray str)
@@ -1217,6 +1226,7 @@
 {"nContextDestroy",                "(I)V",                                 (void*)nContextDestroy },
 {"nAssignName",                    "(I[B)V",                               (void*)nAssignName },
 {"nObjDestroy",                    "(I)V",                                 (void*)nObjDestroy },
+{"nObjDestroyOOB",                 "(I)V",                                 (void*)nObjDestroyOOB },
 
 {"nFileOpen",                      "([B)I",                                (void*)nFileOpen },
 
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index d7d572e..e4cf00f 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -51,6 +51,7 @@
 
 RsContext rsContextCreate(RsDevice, void *, uint32_t version);
 void rsContextDestroy(RsContext);
+void rsObjDestroyOOB(RsContext, void *);
 
 #define RS_MAX_TEXTURE 2
 
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index da9eda8..6d400c5 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -67,8 +67,6 @@
 
     private RenderScript mRS;
     private Allocation mIntAlloc;
-    private Allocation mPartAlloc;
-    private Script mScript;
     private SimpleMesh mSM;
     private SomeData mSD;
     private Type mSDType;
@@ -94,9 +92,9 @@
         mSM = smb.create();
         mSM.setName("PartMesh");
 
-        mPartAlloc = mSM.createVertexAllocation(vtxSlot);
-        mPartAlloc.setName("PartBuffer");
-        mSM.bindVertexAllocation(mPartAlloc, 0);
+        Allocation partAlloc = mSM.createVertexAllocation(vtxSlot);
+        partAlloc.setName("PartBuffer");
+        mSM.bindVertexAllocation(partAlloc, 0);
 
         // All setup of named objects should be done by this point
         // because we are about to compile the script.
@@ -104,12 +102,12 @@
         sb.setScript(mRes, R.raw.fountain);
         sb.setRoot(true);
         sb.setType(mSDType, "Control", 0);
-        mScript = sb.create();
-        mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        Script script = sb.create();
+        script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
-        mScript.bindAllocation(mIntAlloc, 0);
-        mScript.bindAllocation(mPartAlloc, 1);
-        mRS.contextBindRootScript(mScript);
+        script.bindAllocation(mIntAlloc, 0);
+        script.bindAllocation(partAlloc, 1);
+        mRS.contextBindRootScript(script);
     }
 
 }
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index bc0cf12..7bfa81e 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -170,12 +170,14 @@
              mDraw = rsc->runRootScript();
              eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
          }
+         rsc->objDestroyOOBRun();
      }
 
      glClearColor(0,0,0,0);
      glClear(GL_COLOR_BUFFER_BIT);
      eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
      eglTerminate(rsc->mDisplay);
+     rsc->objDestroyOOBRun();
      return NULL;
 }
 
@@ -210,6 +212,8 @@
 
     mWndSurface = sur;
 
+    objDestroyOOBInit();
+
     LOGV("RS Launching thread");
     status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
     if (status) {
@@ -229,11 +233,14 @@
     void *res;
 
     int status = pthread_join(mThreadId, &res);
+    objDestroyOOBRun();
 
     if (mDev) {
         mDev->removeContext(this);
         pthread_key_delete(gThreadTLSKey);
     }
+
+    objDestroyOOBDestroy();
 }
 
 void Context::swapBuffers()
@@ -345,6 +352,62 @@
     }
 }
 
+bool Context::objDestroyOOBInit()
+{
+    int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
+    if (status) {
+        LOGE("Context::ObjDestroyOOBInit mutex init failure");
+        return false;
+    }
+    return true;
+}
+
+void Context::objDestroyOOBRun()
+{
+    if (mObjDestroy.mNeedToEmpty) {
+        int status = pthread_mutex_lock(&mObjDestroy.mMutex);
+        if (status) {
+            LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
+            return;
+        }
+
+        for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) {
+            mObjDestroy.mDestroyList[ct]->decRef();
+        }
+        mObjDestroy.mDestroyList.clear();
+        mObjDestroy.mNeedToEmpty = false;
+
+        status = pthread_mutex_unlock(&mObjDestroy.mMutex);
+        if (status) {
+            LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
+        }
+    }
+}
+
+void Context::objDestroyOOBDestroy()
+{
+    rsAssert(!mObjDestroy.mNeedToEmpty);
+    pthread_mutex_destroy(&mObjDestroy.mMutex);
+}
+
+void Context::objDestroyAdd(ObjectBase *obj)
+{
+    int status = pthread_mutex_lock(&mObjDestroy.mMutex);
+    if (status) {
+        LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
+        return;
+    }
+
+    mObjDestroy.mNeedToEmpty = true;
+    mObjDestroy.mDestroyList.add(obj);
+
+    status = pthread_mutex_unlock(&mObjDestroy.mMutex);
+    if (status) {
+        LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
+    }
+}
+
+
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 //
@@ -429,3 +492,9 @@
     delete rsc;
 }
 
+void rsObjDestroyOOB(RsContext vrsc, void *obj)
+{
+    Context * rsc = static_cast<Context *>(vrsc);
+    rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
+}
+
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 3d17298..52901b2 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -118,6 +118,7 @@
 
 
     ThreadIO mIO;
+    void objDestroyAdd(ObjectBase *);
 
 protected:
     Device *mDev;
@@ -142,6 +143,17 @@
     ObjectBaseRef<ProgramVertex> mVertex;
     ObjectBaseRef<ProgramFragmentStore> mFragmentStore;
 
+
+    struct ObjDestroyOOB {
+        pthread_mutex_t mMutex;
+        Vector<ObjectBase *> mDestroyList;
+        bool mNeedToEmpty;
+    };
+    ObjDestroyOOB mObjDestroy;
+    bool objDestroyOOBInit();
+    void objDestroyOOBRun();
+    void objDestroyOOBDestroy();
+
 private:
     Context();