From f97b29d2e3aefcb4bb31a7b7ead9f651a91e7ff4 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Mon, 6 Apr 2020 12:01:01 -0400 Subject: [PATCH] Switch get_env_or_die to requireEnv Fixes: 153099745 Test: manual The heif decoder may need to continue reading the input from a JavaInputStreamAdaptor on the AnimatedImageThread. Attach the JVM like we do for ByteBufferStream and ByteArrayStream. Similarly, if the AnimatedImageThread is holding a reference to an AnimatedImageDrawable, it is possible to call its destructor, and ultimately InvokeListener's destructor or ByteBufferStreamAdaptor's release_proc on that thread without the JVM attached. Attach in that case, too. Change-Id: I84d236eed2fb5c8617533aed0cae4c762d1eb6dd --- libs/hwui/jni/AnimatedImageDrawable.cpp | 2 +- libs/hwui/jni/ByteBufferStreamAdaptor.cpp | 20 +------------------ .../jni/CreateJavaOutputStreamAdaptor.cpp | 4 ++-- libs/hwui/jni/Utils.cpp | 10 ++++++++++ libs/hwui/jni/Utils.h | 10 ++++++++++ 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp index 055075d0c42a1..1ff156593c41e 100644 --- a/libs/hwui/jni/AnimatedImageDrawable.cpp +++ b/libs/hwui/jni/AnimatedImageDrawable.cpp @@ -183,7 +183,7 @@ public: } ~InvokeListener() override { - auto* env = get_env_or_die(mJvm); + auto* env = requireEnv(mJvm); env->DeleteWeakGlobalRef(mWeakRef); } diff --git a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp index db5f6f6c684fd..b10540cb3fbde 100644 --- a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp +++ b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp @@ -9,24 +9,6 @@ using namespace android; static jmethodID gByteBuffer_getMethodID; static jmethodID gByteBuffer_setPositionMethodID; -/** - * Helper method for accessing the JNI interface pointer. - * - * Image decoding (which this supports) is started on a thread that is already - * attached to the Java VM. But an AnimatedImageDrawable continues decoding on - * the AnimatedImageThread, which is not attached. This will attach if - * necessary. - */ -static JNIEnv* requireEnv(JavaVM* jvm) { - JNIEnv* env; - if (jvm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { - if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) { - LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!"); - } - } - return env; -} - class ByteBufferStream : public SkStreamAsset { private: ByteBufferStream(JavaVM* jvm, jobject jbyteBuffer, size_t initialPosition, size_t length, @@ -304,7 +286,7 @@ std::unique_ptr CreateByteBufferStreamAdaptor(JNIEnv* env, jobject jby auto* context = new release_proc_context{jvm, jbyteBuffer}; auto releaseProc = [](const void*, void* context) { auto* c = reinterpret_cast(context); - JNIEnv* env = get_env_or_die(c->jvm); + JNIEnv* env = requireEnv(c->jvm); env->DeleteGlobalRef(c->jbyteBuffer); delete c; }; diff --git a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp index 39483b55992b4..f1c6b29204b23 100644 --- a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp +++ b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp @@ -49,13 +49,13 @@ public: } ~JavaInputStreamAdaptor() override { - auto* env = android::get_env_or_die(fJvm); + auto* env = android::requireEnv(fJvm); env->DeleteGlobalRef(fJavaInputStream); env->DeleteGlobalRef(fJavaByteArray); } size_t read(void* buffer, size_t size) override { - auto* env = android::get_env_or_die(fJvm); + auto* env = android::requireEnv(fJvm); if (!fSwallowExceptions && checkException(env)) { // Just in case the caller did not clear from a previous exception. return 0; diff --git a/libs/hwui/jni/Utils.cpp b/libs/hwui/jni/Utils.cpp index 17c194d04f848..34fd6687d52ca 100644 --- a/libs/hwui/jni/Utils.cpp +++ b/libs/hwui/jni/Utils.cpp @@ -159,3 +159,13 @@ JNIEnv* android::get_env_or_die(JavaVM* jvm) { } return env; } + +JNIEnv* android::requireEnv(JavaVM* jvm) { + JNIEnv* env; + if (jvm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) { + LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!"); + } + } + return env; +} diff --git a/libs/hwui/jni/Utils.h b/libs/hwui/jni/Utils.h index 89255177ba2ef..f628cc3c85ede 100644 --- a/libs/hwui/jni/Utils.h +++ b/libs/hwui/jni/Utils.h @@ -78,6 +78,16 @@ bool isSeekable(int descriptor); JNIEnv* get_env_or_die(JavaVM* jvm); +/** + * Helper method for accessing the JNI interface pointer. + * + * Image decoding (which this supports) is started on a thread that is already + * attached to the Java VM. But an AnimatedImageDrawable continues decoding on + * the AnimatedImageThread, which is not attached. This will attach if + * necessary. + */ +JNIEnv* requireEnv(JavaVM* jvm); + }; // namespace android #endif // _ANDROID_GRAPHICS_UTILS_H_