summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Leon Scroggins III <scroggo@google.com> 2019-09-11 12:33:00 -0400
committer John Reck <jreck@google.com> 2019-10-10 18:03:07 +0000
commit84d069d1c97e9a7c89ccf9c35afff01363ef8e4c (patch)
tree5b2c7bb82453c9dc0114d94124a0b7a59c4f6822
parent678feaf43a97b10fb107eef80881d696d85cd5df (diff)
Fix AnimatedImageDrawables using ByteBuffers
Bug: 140715166 Test: I56dc6e9865c2701746c95ea584bcc70fe4d62a6c AnimatedImageDrawable, when created from a ByteBuffer, needs to get a pointer to the JNI interface in order to read the ByteBuffer (or byte[]). But the AnimatedImageThread is not attached to the JVM. Attach it as necessary. Change-Id: I51b69b5b70f8c5865d5e5ed065e42267fa556202 Merged-In: I51b69b5b70f8c5865d5e5ed065e42267fa556202 (cherry picked from commit a7ec12f7efc032211e54aa1ce28c698413f02b8d)
-rw-r--r--core/jni/android/graphics/ByteBufferStreamAdaptor.cpp29
1 files changed, 24 insertions, 5 deletions
diff --git a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp
index 173818b13837..d443fd8cdf14 100644
--- a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp
+++ b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp
@@ -1,6 +1,7 @@
#include "ByteBufferStreamAdaptor.h"
#include "core_jni_helpers.h"
#include "Utils.h"
+#include <jni.h>
#include <SkStream.h>
@@ -9,6 +10,24 @@ 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<void**>(&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,
@@ -46,7 +65,7 @@ public:
}
~ByteBufferStream() override {
- auto* env = get_env_or_die(mJvm);
+ auto* env = requireEnv(mJvm);
env->DeleteGlobalRef(mByteBuffer);
env->DeleteGlobalRef(mStorage);
}
@@ -63,7 +82,7 @@ public:
return this->setPosition(mPosition + size) ? size : 0;
}
- auto* env = get_env_or_die(mJvm);
+ auto* env = requireEnv(mJvm);
size_t bytesRead = 0;
do {
const size_t requested = (size > kStorageSize) ? kStorageSize : size;
@@ -146,7 +165,7 @@ private:
// Range has already been checked by the caller.
bool setPosition(size_t newPosition) {
- auto* env = get_env_or_die(mJvm);
+ auto* env = requireEnv(mJvm);
env->CallObjectMethod(mByteBuffer, gByteBuffer_setPositionMethodID,
newPosition + mInitialPosition);
if (env->ExceptionCheck()) {
@@ -185,7 +204,7 @@ public:
}
~ByteArrayStream() override {
- auto* env = get_env_or_die(mJvm);
+ auto* env = requireEnv(mJvm);
env->DeleteGlobalRef(mByteArray);
}
@@ -197,7 +216,7 @@ public:
return 0;
}
- auto* env = get_env_or_die(mJvm);
+ auto* env = requireEnv(mJvm);
if (buffer) {
env->GetByteArrayRegion(mByteArray, mPosition + mOffset, size,
reinterpret_cast<jbyte*>(buffer));