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

Commit ab45cf3d authored by John Reck's avatar John Reck
Browse files

Fix SurfaceTexture listener performance

Attaching & detaching threads from JavaVM isn't cheap. There's
no reason to do a detach anyway, so just don't. This avoids
subsequent callbacks needing to re-attach.

This aligns SurfaceTexture to the common pattern elsewhere
in the platform for attaching as a daemon if it's not a java
thread.

Fixes: 26842782
Test: make
Change-Id: I9bebe288dc8896c1f2c47cc1b02409526926cef7
parent b1635458
Loading
Loading
Loading
Loading
+5 −24
Original line number Diff line number Diff line
@@ -147,8 +147,7 @@ public:
    virtual void onFrameAvailable(const BufferItem& item);

private:
    static JNIEnv* getJNIEnv(bool* needsDetach);
    static void detachJNI();
    static JNIEnv* getJNIEnv();

    jobject mWeakThiz;
    jclass mClazz;
@@ -160,58 +159,40 @@ JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env,
    mClazz((jclass)env->NewGlobalRef(clazz))
{}

JNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) {
    *needsDetach = false;
JNIEnv* JNISurfaceTextureContext::getJNIEnv() {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    if (env == NULL) {
        JavaVMAttachArgs args = {
            JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL };
        JavaVM* vm = AndroidRuntime::getJavaVM();
        int result = vm->AttachCurrentThread(&env, (void*) &args);
        int result = vm->AttachCurrentThreadAsDaemon(&env, (void*)&args);
        if (result != JNI_OK) {
            ALOGE("thread attach failed: %#x", result);
            return NULL;
        }
        *needsDetach = true;
    }
    return env;
}

void JNISurfaceTextureContext::detachJNI() {
    JavaVM* vm = AndroidRuntime::getJavaVM();
    int result = vm->DetachCurrentThread();
    if (result != JNI_OK) {
        ALOGE("thread detach failed: %#x", result);
    }
}

JNISurfaceTextureContext::~JNISurfaceTextureContext()
{
    bool needsDetach = false;
    JNIEnv* env = getJNIEnv(&needsDetach);
    JNIEnv* env = getJNIEnv();
    if (env != NULL) {
        env->DeleteGlobalRef(mWeakThiz);
        env->DeleteGlobalRef(mClazz);
    } else {
        ALOGW("leaking JNI object references");
    }
    if (needsDetach) {
        detachJNI();
    }
}

void JNISurfaceTextureContext::onFrameAvailable(const BufferItem& /* item */)
{
    bool needsDetach = false;
    JNIEnv* env = getJNIEnv(&needsDetach);
    JNIEnv* env = getJNIEnv();
    if (env != NULL) {
        env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
    } else {
        ALOGW("onFrameAvailable event will not posted");
    }
    if (needsDetach) {
        detachJNI();
    }
}

// ----------------------------------------------------------------------------