Implement OOB destroy method that can be called from the java finalizer removing the need to explicitly destroy objects.
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..7bfa81ed 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();