summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2013-09-20 00:08:58 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-09-20 00:08:58 +0000
commit9d53e30e5eaf53cb0bd57319e02025ba7182bba3 (patch)
treec4f10d13b698a6eaaca65b561347645a04e153eb /core/jni
parenta17309fd9ed705bb3a9d7adbf3b30eb71952dabc (diff)
parent8d87d7ba113ad90685f1d2669e65251a9b422a5a (diff)
downloadframeworks_base-9d53e30e5eaf53cb0bd57319e02025ba7182bba3.zip
frameworks_base-9d53e30e5eaf53cb0bd57319e02025ba7182bba3.tar.gz
frameworks_base-9d53e30e5eaf53cb0bd57319e02025ba7182bba3.tar.bz2
Merge "Workaround for slow AudioRecord destructor" into klp-dev
Diffstat (limited to 'core/jni')
-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
+ }
}