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

Commit 09a903ab authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 7696 into donut

* changes:
  add hidden Options field for native allocations
parents 41f338c6 1b22b979
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -224,7 +224,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
    SkBitmap bitmap;

    bitmap.setConfig(config, width, height);
    if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL)) {
    if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true)) {
        return NULL;
    }

@@ -240,7 +240,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
                           SkBitmap::Config dstConfig, jboolean isMutable) {
    SkBitmap            result;
    JavaPixelAllocator  allocator(env);
    JavaPixelAllocator  allocator(env, true);

    if (!src->copyTo(&result, dstConfig, &allocator)) {
        return NULL;
@@ -356,7 +356,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
        }
    }

    if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable)) {
    if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, true)) {
        ctable->safeUnref();
        delete bitmap;
        return NULL;
+9 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ static jfieldID gOptions_configFieldID;
static jfieldID gOptions_ditherFieldID;
static jfieldID gOptions_purgeableFieldID;
static jfieldID gOptions_shareableFieldID;
static jfieldID gOptions_nativeAllocFieldID;
static jfieldID gOptions_widthFieldID;
static jfieldID gOptions_heightFieldID;
static jfieldID gOptions_mimeFieldID;
@@ -300,6 +301,11 @@ static bool optionsShareable(JNIEnv* env, jobject options) {
            env->GetBooleanField(options, gOptions_shareableFieldID);
}

static bool optionsReportSizeToVM(JNIEnv* env, jobject options) {
    return NULL == options ||
            !env->GetBooleanField(options, gOptions_nativeAllocFieldID);
}

static jobject nullObjectReturn(const char msg[]) {
    if (msg) {
        SkDebugf("--- %s\n", msg);
@@ -330,6 +336,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
    bool doDither = true;
    bool isPurgeable = allowPurgeable && optionsPurgeable(env, options);
    bool reportSizeToVM = optionsReportSizeToVM(env, options);
    
    if (NULL != options) {
        sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
@@ -355,7 +362,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
    decoder->setDitherImage(doDither);

    NinePatchPeeker     peeker;
    JavaPixelAllocator  javaAllocator(env);
    JavaPixelAllocator  javaAllocator(env, reportSizeToVM);
    SkBitmap*           bitmap = new SkBitmap;
    Res_png_9patch      dummy9Patch;

@@ -699,6 +706,7 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
    gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z");
    gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z");
    gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z");
    gOptions_nativeAllocFieldID = getFieldIDCheck(env, gOptions_class, "inNativeAlloc", "Z");
    gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I");
    gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I");
    gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;");
+31 −25
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h>

//#define REPORT_SIZE_TO_JVM
//#define TRACK_LOCK_COUNT

void doThrow(JNIEnv* env, const char* exc, const char* msg) {
@@ -444,7 +445,7 @@ private:
};

bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                  SkColorTable* ctable) {
                                  SkColorTable* ctable, bool reportSizeToVM) {
    Sk64 size64 = bitmap->getSize64();
    if (size64.isNeg() || !size64.is32()) {
        doThrow(env, "java/lang/IllegalArgumentException",
@@ -453,8 +454,9 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
    }
    
    size_t size = size64.get32();
    //    SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
    jlong jsize = size;  // the VM wants longs for the size
    if (reportSizeToVM) {
        //    SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
        bool r = env->CallBooleanMethod(gVMRuntime_singleton,
                                    gVMRuntime_trackExternalAllocationMethodID,
                                    jsize);
@@ -466,10 +468,11 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
            doThrowOOME(env, "bitmap size exceeds VM budget");
            return false;
        }
    
    }
    // call the version of malloc that returns null on failure
    void* addr = sk_malloc_flags(size, 0);
    if (NULL == addr) {
        if (reportSizeToVM) {
            //        SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size);
            // we didn't actually allocate it, so inform the VM
            env->CallVoidMethod(gVMRuntime_singleton,
@@ -478,10 +481,14 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
            if (!GraphicsJNI::hasException(env)) {
                doThrowOOME(env, "bitmap size too large for malloc");
            }
        }
        return false;
    }
    
    bitmap->setPixelRef(new AndroidPixelRef(env, addr, size, ctable))->unref();
    SkPixelRef* pr = reportSizeToVM ?
                        new AndroidPixelRef(env, addr, size, ctable) :
                        new SkMallocPixelRef(addr, size, ctable);
    bitmap->setPixelRef(pr)->unref();
    // since we're already allocated, we lockPixels right away
    // HeapAllocator behaves this way too
    bitmap->lockPixels();
@@ -490,12 +497,11 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,

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

JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) : fEnv(env)
{
}
JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM)
    : fEnv(env), fReportSizeToVM(reportSizeToVM) {}
    
bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
    return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable);
    return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable, fReportSizeToVM);
}

////////////////////////////////////////////////////////////////////////////////
+4 −2
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ public:
        Returns true on success. If it returns false, then it failed, and the
        appropriate exception will have been raised.
    */
    static bool setJavaPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable);
    static bool setJavaPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable,
                                bool reportSizeToVM);

    /** Copy the colors in colors[] to the bitmap, convert to the correct
        format along the way.
@@ -71,12 +72,13 @@ public:

class JavaPixelAllocator : public SkBitmap::Allocator {
public:
    JavaPixelAllocator(JNIEnv* env);
    JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM);
    // overrides
    virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
    
private:
    JNIEnv* fEnv;
    bool fReportSizeToVM;
};

class AutoJavaFloatArray {
+13 −0
Original line number Diff line number Diff line
@@ -128,6 +128,19 @@ public class BitmapFactory {
         */
        public boolean inInputShareable;

        /**
         * Normally bitmap allocations count against the dalvik heap, which
         * means they help trigger GCs when a lot have been allocated. However,
         * in rare cases, the caller may want to allocate the bitmap outside of
         * that heap. To request that, set inNativeAlloc to true. In these
         * rare instances, it is solely up to the caller to ensure that OOM is
         * managed explicitly by calling bitmap.recycle() as soon as such a
         * bitmap is no longer needed.
         *
         * @hide pending API council approval
         */
        public boolean inNativeAlloc;

        /**
         * The resulting width of the bitmap, set independent of the state of
         * inJustDecodeBounds. However, if there is an error trying to decode,