From ca35e4823459189dd57ec5472caf3a617d03b568 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 17 Jul 2013 17:26:41 -0700 Subject: [PATCH] Fix media server restart detection mechanism There is a flaw in the mechanism used by AudioService to detect the fact that mediaserver process did crash and restart. It relies on polling AudioFlinger service until a successful connection triggers a callback into AudioSystem JNI and then into AudioService. But if another thread in system_server process, not attached to the JNI environment, reconnects before AudioService, the callback is called in a detached context and dropped. The fix consists in attaching the thread executing the callback and detaching it if needed. Bug: 9693068. Change-Id: I184308b12a3f87653bf818abf0159e0e45a66ef0 --- core/jni/android_media_AudioSystem.cpp | 32 +++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 67c2cfdc9bb3c..45561d3e4ea78 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -117,10 +117,36 @@ android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys) return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string()); } +static JNIEnv* AudioSystem_getJNIEnv(bool* needsDetach) { + *needsDetach = false; + JNIEnv* env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; + JavaVM* vm = AndroidRuntime::getJavaVM(); + int result = vm->AttachCurrentThread(&env, (void*) &args); + if (result != JNI_OK) { + ALOGE("thread attach failed: %#x", result); + return NULL; + } + *needsDetach = true; + } + return env; +} + +static void AudioSystem_detachJNI() { + JavaVM* vm = AndroidRuntime::getJavaVM(); + int result = vm->DetachCurrentThread(); + if (result != JNI_OK) { + ALOGE("thread detach failed: %#x", result); + } +} + static void android_media_AudioSystem_error_callback(status_t err) { - JNIEnv *env = AndroidRuntime::getJNIEnv(); + bool needsDetach = false; + JNIEnv *env = AudioSystem_getJNIEnv(&needsDetach); + if (env == NULL) { return; } @@ -142,6 +168,10 @@ android_media_AudioSystem_error_callback(status_t err) } env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error); + + if (needsDetach) { + AudioSystem_detachJNI(); + } } static int