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

Commit 94b19d37 authored by Joseph Wen's avatar Joseph Wen Committed by Android Git Automerger
Browse files

am 94db0238: am 219eb7ec: Merge "Fix bug in JNI BitmapFactory" into gingerbread

Merge commit '94db0238'

* commit '94db0238':
  Fix bug in JNI BitmapFactory
parents a97ccc02 94db0238
Loading
Loading
Loading
Loading
+64 −36
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
#include <utils/ResourceTypes.h>
#include <utils/ResourceTypes.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/stat.h>


jclass gOptions_class;
jclass gOptions_class;
jfieldID gOptions_justBoundsFieldID;
jfieldID gOptions_justBoundsFieldID;
@@ -559,7 +560,27 @@ static void nativeSetDefaultConfig(JNIEnv* env, jobject, int nativeConfig) {
    }
    }
}
}


static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) {
static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
    size_t bufferSize = 4096;
    size_t streamLen = 0;
    size_t len;
    char* data = (char*)sk_malloc_throw(bufferSize);

    while ((len = stream->read(data + streamLen,
                    bufferSize - streamLen)) != 0) {
        streamLen += len;
        if (streamLen == bufferSize) {
            bufferSize *= 2;
            data = (char*)sk_realloc_throw(data, bufferSize);
        }
    }
    data = (char*)sk_realloc_throw(data, streamLen);
    SkMemoryStream* streamMem = new SkMemoryStream();
    streamMem->setMemoryOwned(data, streamLen);
    return streamMem;
}

static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) {
    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
    int width, height;
    int width, height;
    if (NULL == decoder) {
    if (NULL == decoder) {
@@ -574,9 +595,10 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable)
    javaAllocator->unref();
    javaAllocator->unref();
    javaMemoryReporter->unref();
    javaMemoryReporter->unref();


    if (!decoder->buildTileIndex(stream, &width, &height, isShareable)) {
    if (!decoder->buildTileIndex(stream, &width, &height)) {
        char msg[1024];
        char msg[100];
        snprintf(msg, 1023, "Image failed to decode using %s decoder", decoder->getFormatName());
        snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder",
                decoder->getFormatName());
        doThrowIOE(env, msg);
        doThrowIOE(env, msg);
        return nullObjectReturn("decoder->buildTileIndex returned false");
        return nullObjectReturn("decoder->buildTileIndex returned false");
    }
    }
@@ -588,13 +610,13 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable)


static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
                                     int offset, int length, jboolean isShareable) {
                                     int offset, int length, jboolean isShareable) {
    /*  If isShareable we could decide to just wrap the java array and
        share it, but that means adding a globalref to the java array object
        For now we just always copy the array's data if isShareable.
     */
    AutoJavaByteArray ar(env, byteArray);
    AutoJavaByteArray ar(env, byteArray);
    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false);
    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
    SkAutoUnref aur(stream);
    return doBuildTileIndex(env, stream);
    if (isShareable) {
        aur.detach();
    }
    return doBuildTileIndex(env, stream, isShareable);
}
}


static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz,
static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz,
@@ -603,24 +625,31 @@ static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject cl


    jint descriptor = env->GetIntField(fileDescriptor,
    jint descriptor = env->GetIntField(fileDescriptor,
                                       gFileDescriptor_descriptor);
                                       gFileDescriptor_descriptor);
    bool weOwnTheFD = false;
    SkStream *stream = NULL;

    struct stat fdStat;
    if (isShareable) {
    int newFD;
        int newFD = ::dup(descriptor);
    if (fstat(descriptor, &fdStat) == -1) {
        if (-1 != newFD) {
        doThrowIOE(env, "broken file descriptor");
            weOwnTheFD = true;
        return nullObjectReturn("fstat return -1");
            descriptor = newFD;
    }
        }

    if (isShareable &&
            S_ISREG(fdStat.st_mode) &&
            (newFD = ::dup(descriptor)) != -1) {
        SkFDStream* fdStream = new SkFDStream(newFD, true);
        if (!fdStream->isValid()) {
            fdStream->unref();
            return NULL;
        }
        }

        stream = fdStream;
    SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD);
    } else {
    SkAutoUnref aur(stream);
        SkFDStream* fdStream = new SkFDStream(descriptor, false);
    if (!stream->isValid()) {
        if (!fdStream->isValid()) {
            fdStream->unref();
            return NULL;
            return NULL;
        }
        }

        stream = buildSkMemoryStream(fdStream);
    if (isShareable) {
        fdStream->unref();
        aur.detach();
    }
    }


    /* Restore our offset when we leave, so we can be called more than once
    /* Restore our offset when we leave, so we can be called more than once
@@ -629,7 +658,7 @@ static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject cl
    */
    */
    AutoFDSeek as(descriptor);
    AutoFDSeek as(descriptor);


    return doBuildTileIndex(env, stream, isShareable);
    return doBuildTileIndex(env, stream);
}
}


static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz,
static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz,
@@ -641,7 +670,8 @@ static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz,


    if (stream) {
    if (stream) {
        // for now we don't allow shareable with java inputstreams
        // for now we don't allow shareable with java inputstreams
        largeBitmap = doBuildTileIndex(env, stream, false);
        SkMemoryStream *mStream = buildSkMemoryStream(stream);
        largeBitmap = doBuildTileIndex(env, mStream);
        stream->unref();
        stream->unref();
    }
    }
    return largeBitmap;
    return largeBitmap;
@@ -650,14 +680,12 @@ static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz,
static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz,
static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz,
                                 jint native_asset, // Asset
                                 jint native_asset, // Asset
                                 jboolean isShareable) {
                                 jboolean isShareable) {
    SkStream* stream;
    SkStream* stream, *assStream;
    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    stream = new AssetStreamAdaptor(asset);
    assStream = new AssetStreamAdaptor(asset);
    SkAutoUnref aur(stream);
    stream = buildSkMemoryStream(assStream);
    if (isShareable) {
    assStream->unref();
        aur.detach();
    return doBuildTileIndex(env, stream);
    }
    return doBuildTileIndex(env, stream, isShareable);
}
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////