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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user