summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_media_AudioRecord.cpp23
1 files changed, 23 insertions, 0 deletions
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 1c43cc5..3994047 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -310,6 +310,18 @@ android_media_AudioRecord_stop(JNIEnv *env, jobject thiz)
// ----------------------------------------------------------------------------
+// This class is used to destroy a RefBase asynchronously
+class AsyncDestructThread : public Thread
+{
+public:
+ AsyncDestructThread(sp<RefBase> refBase) : mRefBase(refBase) { }
+protected:
+ virtual ~AsyncDestructThread() { }
+private:
+ virtual bool threadLoop() { return false; }
+ const sp<RefBase> mRefBase;
+};
+
#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000
static void android_media_AudioRecord_release(JNIEnv *env, jobject thiz) {
sp<AudioRecord> lpRecorder = setAudioRecord(env, thiz, 0);
@@ -342,6 +354,17 @@ static void android_media_AudioRecord_release(JNIEnv *env, jobject thiz) {
env->DeleteGlobalRef(lpCookie->audioRecord_ref);
delete lpCookie;
}
+ // FIXME AudioRecord destruction should not be slow
+ if (lpRecorder != 0) {
+ // must be a raw reference to avoid a race after run()
+ AsyncDestructThread *adt = new AsyncDestructThread(lpRecorder);
+ // guaranteed to not run destructor
+ lpRecorder.clear();
+ // after the run(), adt thread will hold a strong reference to lpRecorder,
+ // and the only strong reference to itself
+ adt->run("AsyncDestruct");
+ // do not delete adt here: adt thread destroys itself, and lpRecorder if needed
+ }
}