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

Commit 3019d9c8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix AnimatedImageDrawables using ByteBuffers"

parents 725f1e8f a7ec12f7
Loading
Loading
Loading
Loading
+24 −5
Original line number Diff line number Diff line
#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));