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
This commit is contained in:
Eric Laurent
2013-07-17 17:26:41 -07:00
parent 713412fd54
commit ca35e48234

View File

@@ -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