Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca35e482 authored by Eric Laurent's avatar Eric Laurent
Browse files

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
parent 713412fd
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -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