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

Commit 3393f390 authored by Leon Scroggins III's avatar Leon Scroggins III Committed by Android (Google) Code Review
Browse files

Merge "Decode file descriptor from the correct offset."

parents eaddb849 2826e5f2
Loading
Loading
Loading
Loading
+42 −21
Original line number Diff line number Diff line
@@ -474,6 +474,12 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
            bitmapCreateFlags, ninePatchChunk, layoutBounds, -1);
}

// Need to buffer enough input to be able to rewind as much as might be read by a decoder
// trying to determine the stream's format. Currently the most is 64, read by
// SkImageDecoder_libwebp.
// FIXME: Get this number from SkImageDecoder
#define BYTES_TO_BUFFER 64

static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
        jobject padding, jobject options) {

@@ -481,11 +487,8 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
    SkAutoTUnref<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage));

    if (stream.get()) {
        // Need to buffer enough input to be able to rewind as much as might be read by a decoder
        // trying to determine the stream's format. Currently the most is 64, read by
        // SkImageDecoder_libwebp.
        // FIXME: Get this number from SkImageDecoder
        SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(stream, 64));
        SkAutoTUnref<SkStreamRewindable> bufferedStream(
                SkFrontBufferedStream::Create(stream, BYTES_TO_BUFFER));
        SkASSERT(bufferedStream.get() != NULL);
        // for now we don't allow purgeable with java inputstreams
        bitmap = doDecode(env, bufferedStream, padding, options, false, false);
@@ -506,30 +509,48 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
        return nullObjectReturn("fstat return -1");
    }

    bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions);
    bool isShareable = optionsShareable(env, bitmapFactoryOptions);
    bool weOwnTheFD = false;
    if (isPurgeable && isShareable) {
        int newFD = ::dup(descriptor);
        if (-1 != newFD) {
            weOwnTheFD = true;
            descriptor = newFD;
        }
    }
    // Restore the descriptor's offset on exiting this function.
    AutoFDSeek autoRestore(descriptor);

    FILE* file = fdopen(descriptor, "r");
    if (file == NULL) {
        return nullObjectReturn("Could not open file");
    }

    SkAutoTUnref<SkFILEStream> stream(new SkFILEStream(file,
            weOwnTheFD ? SkFILEStream::kCallerPasses_Ownership :
    SkAutoTUnref<SkFILEStream> fileStream(new SkFILEStream(file,
                         SkFILEStream::kCallerRetains_Ownership));

    /* Allow purgeable iff we own the FD, i.e., in the puregeable and
       shareable case.
    */
    return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
    SkAutoTUnref<SkStreamRewindable> stream;

    // Retain the old behavior of allowing purgeable if both purgeable and
    // shareable are set to true.
    bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions)
                       && optionsShareable(env, bitmapFactoryOptions);
    if (isPurgeable) {
        // Copy the stream, so the image can be decoded multiple times without
        // continuing to modify the original file descriptor.
        // Copy beginning from the current position.
        const size_t fileSize = fileStream->getLength() - fileStream->getPosition();
        void* buffer = sk_malloc_flags(fileSize, 0);
        if (buffer == NULL) {
            return nullObjectReturn("Could not make a copy for ashmem");
        }

        SkAutoTUnref<SkData> data(SkData::NewFromMalloc(buffer, fileSize));

        if (fileStream->read(buffer, fileSize) != fileSize) {
            return nullObjectReturn("Could not read the file.");
        }

        stream.reset(new SkMemoryStream(data));
    } else {
        // Use a buffered stream. Although an SkFILEStream can be rewound, this
        // ensures that SkImageDecoder::Factory never rewinds beyond the
        // current position of the file descriptor.
        stream.reset(SkFrontBufferedStream::Create(fileStream, BYTES_TO_BUFFER));
    }

    return doDecode(env, stream, padding, bitmapFactoryOptions, isPurgeable);
}

static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset,