Revert "Rename LargeBitmap to BitmapRegionDecoder for having a better API."

This reverts commit 50ba3d2c09a9131f3578d271adf2bc8258ca1742.
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index cc67e44..42135c5 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -102,12 +102,11 @@
 	android_graphics_PixelFormat.cpp \
 	android/graphics/Picture.cpp \
 	android/graphics/PorterDuff.cpp \
-	android/graphics/BitmapRegionDecoder.cpp \
+	android/graphics/LargeBitmap.cpp \
 	android/graphics/Rasterizer.cpp \
 	android/graphics/Region.cpp \
 	android/graphics/Shader.cpp \
 	android/graphics/Typeface.cpp \
-	android/graphics/Utils.cpp \
 	android/graphics/Xfermode.cpp \
 	android/graphics/YuvToJpegEncoder.cpp \
 	android_media_AudioRecord.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d6b61e9..2751a82 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -53,7 +53,7 @@
 extern int register_android_os_Process(JNIEnv* env);
 extern int register_android_graphics_Bitmap(JNIEnv*);
 extern int register_android_graphics_BitmapFactory(JNIEnv*);
-extern int register_android_graphics_BitmapRegionDecoder(JNIEnv*);
+extern int register_android_graphics_LargeBitmap(JNIEnv*);
 extern int register_android_graphics_Camera(JNIEnv* env);
 extern int register_android_graphics_Graphics(JNIEnv* env);
 extern int register_android_graphics_Interpolator(JNIEnv* env);
@@ -1244,7 +1244,7 @@
 
     REG_JNI(register_android_graphics_Bitmap),
     REG_JNI(register_android_graphics_BitmapFactory),
-    REG_JNI(register_android_graphics_BitmapRegionDecoder),
+    REG_JNI(register_android_graphics_LargeBitmap),
     REG_JNI(register_android_graphics_Camera),
     REG_JNI(register_android_graphics_Canvas),
     REG_JNI(register_android_graphics_ColorFilter),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 48539dc..254d9a4 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -10,7 +10,6 @@
 #include "SkUtils.h"
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "AutoDecodeCancel.h"
-#include "Utils.h"
 
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/Asset.h>
@@ -99,6 +98,57 @@
     }
 };
 
+class AssetStreamAdaptor : public SkStream {
+public:
+    AssetStreamAdaptor(Asset* a) : fAsset(a) {}
+    
+    virtual bool rewind() {
+        off_t pos = fAsset->seek(0, SEEK_SET);
+        if (pos == (off_t)-1) {
+            SkDebugf("----- fAsset->seek(rewind) failed\n");
+            return false;
+        }
+        return true;
+    }
+    
+    virtual size_t read(void* buffer, size_t size) {
+        ssize_t amount;
+        
+        if (NULL == buffer) {
+            if (0 == size) {  // caller is asking us for our total length
+                return fAsset->getLength();
+            }
+            // asset->seek returns new total offset
+            // we want to return amount that was skipped
+
+            off_t oldOffset = fAsset->seek(0, SEEK_CUR);
+            if (-1 == oldOffset) {
+                SkDebugf("---- fAsset->seek(oldOffset) failed\n");
+                return 0;
+            }
+            off_t newOffset = fAsset->seek(size, SEEK_CUR);
+            if (-1 == newOffset) {
+                SkDebugf("---- fAsset->seek(%d) failed\n", size);
+                return 0;
+            }
+            amount = newOffset - oldOffset;
+        } else {
+            amount = fAsset->read(buffer, size);
+            if (amount <= 0) {
+                SkDebugf("---- fAsset->read(%d) returned %d\n", size, amount);
+            }
+        }
+        
+        if (amount < 0) {
+            amount = 0;
+        }
+        return amount;
+    }
+    
+private:
+    Asset*  fAsset;
+};
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static inline int32_t validOrNeg1(bool isValid, int32_t value) {
@@ -150,6 +200,12 @@
             !env->GetBooleanField(options, gOptions_nativeAllocFieldID);
 }
 
+static jobject nullObjectReturn(const char msg[]) {
+    if (msg) {
+        SkDebugf("--- %s\n", msg);
+    }
+    return NULL;
+}
 
 static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
                                    int sampleSize, bool ditherImage) {
@@ -320,6 +376,23 @@
     return size;
 }
 
+/** Restore the file descriptor's offset in our destructor
+ */
+class AutoFDSeek {
+public:
+    AutoFDSeek(int fd) : fFD(fd) {
+        fCurr = ::lseek(fd, 0, SEEK_CUR);
+    }
+    ~AutoFDSeek() {
+        if (fCurr >= 0) {
+            ::lseek(fFD, fCurr, SEEK_SET);
+        }
+    }
+private:
+    int     fFD;
+    off_t   fCurr;
+};
+
 static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz,
                                           jobject fileDescriptor,
                                           jobject padding,
@@ -486,6 +559,107 @@
     }
 }
 
+static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) {
+    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
+    int width, height;
+    if (NULL == decoder) {
+        doThrowIOE(env, "Image format not supported");
+        return nullObjectReturn("SkImageDecoder::Factory returned null");
+    }
+
+    JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true);
+    decoder->setAllocator(javaAllocator);
+    JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env);
+    decoder->setReporter(javaMemoryReporter);
+    javaAllocator->unref();
+    javaMemoryReporter->unref();
+
+    if (!decoder->buildTileIndex(stream, &width, &height, isShareable)) {
+        char msg[1024];
+        snprintf(msg, 1023, "Image failed to decode using %s decoder", decoder->getFormatName());
+        doThrowIOE(env, msg);
+        return nullObjectReturn("decoder->buildTileIndex returned false");
+    }
+
+    SkLargeBitmap *bm = new SkLargeBitmap(decoder, width, height);
+
+    return GraphicsJNI::createLargeBitmap(env, bm);
+}
+
+static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
+                                     int offset, int length, jboolean isShareable) {
+    AutoJavaByteArray ar(env, byteArray);
+    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false);
+    SkAutoUnref aur(stream);
+    if (isShareable) {
+        aur.detach();
+    }
+    return doBuildTileIndex(env, stream, isShareable);
+}
+
+static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz,
+                                          jobject fileDescriptor, jboolean isShareable) {
+    NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
+
+    jint descriptor = env->GetIntField(fileDescriptor,
+                                       gFileDescriptor_descriptor);
+    bool weOwnTheFD = false;
+
+    if (isShareable) {
+        int newFD = ::dup(descriptor);
+        if (-1 != newFD) {
+            weOwnTheFD = true;
+            descriptor = newFD;
+        }
+    }
+
+    SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD);
+    SkAutoUnref aur(stream);
+    if (!stream->isValid()) {
+        return NULL;
+    }
+
+    if (isShareable) {
+        aur.detach();
+    }
+
+    /* Restore our offset when we leave, so we can be called more than once
+       with the same descriptor. This is only required if we didn't dup the
+       file descriptor, but it is OK to do it all the time.
+    */
+    AutoFDSeek as(descriptor);
+
+    return doBuildTileIndex(env, stream, isShareable);
+}
+
+static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz,
+                                  jobject is,       // InputStream
+                                  jbyteArray storage, // byte[]
+                                  jboolean isShareable) {
+    jobject largeBitmap = NULL;
+    SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
+
+    if (stream) {
+        // for now we don't allow shareable with java inputstreams
+        largeBitmap = doBuildTileIndex(env, stream, false);
+        stream->unref();
+    }
+    return largeBitmap;
+}
+
+static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz,
+                                 jint native_asset, // Asset
+                                 jboolean isShareable) {
+    SkStream* stream;
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    stream = new AssetStreamAdaptor(asset);
+    SkAutoUnref aur(stream);
+    if (isShareable) {
+        aur.detach();
+    }
+    return doBuildTileIndex(env, stream, isShareable);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static JNINativeMethod gMethods[] = {
@@ -515,6 +689,26 @@
     },
 
     {   "nativeSetDefaultConfig", "(I)V", (void*)nativeSetDefaultConfig },
+
+    {   "nativeCreateLargeBitmap",
+        "([BIIZ)Landroid/graphics/LargeBitmap;",
+        (void*)nativeCreateLargeBitmapFromByteArray
+    },
+
+    {   "nativeCreateLargeBitmap",
+        "(Ljava/io/InputStream;[BZ)Landroid/graphics/LargeBitmap;",
+        (void*)nativeCreateLargeBitmapFromStream
+    },
+
+    {   "nativeCreateLargeBitmap",
+        "(Ljava/io/FileDescriptor;Z)Landroid/graphics/LargeBitmap;",
+        (void*)nativeCreateLargeBitmapFromFileDescriptor
+    },
+
+    {   "nativeCreateLargeBitmap",
+        "(IZ)Landroid/graphics/LargeBitmap;",
+        (void*)nativeCreateLargeBitmapFromAsset
+    },
 };
 
 static JNINativeMethod gOptionsMethods[] = {
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
deleted file mode 100644
index 6a5be44..0000000
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BitmapRegionDecoder"
-
-#include "SkBitmap.h"
-#include "SkImageEncoder.h"
-#include "GraphicsJNI.h"
-#include "SkUtils.h"
-#include "SkTemplates.h"
-#include "SkPixelRef.h"
-#include "SkStream.h"
-#include "BitmapFactory.h"
-#include "AutoDecodeCancel.h"
-#include "SkBitmapRegionDecoder.h"
-#include "CreateJavaOutputStreamAdaptor.h"
-#include "Utils.h"
-
-#include <android_runtime/AndroidRuntime.h>
-#include "android_util_Binder.h"
-#include "android_nio_utils.h"
-#include "CreateJavaOutputStreamAdaptor.h"
-
-#include <binder/Parcel.h>
-#include <jni.h>
-#include <utils/Asset.h>
-
-static jclass gFileDescriptor_class;
-static jfieldID gFileDescriptor_descriptor;
-
-#if 0
-    #define TRACE_BITMAP(code)  code
-#else
-    #define TRACE_BITMAP(code)
-#endif
-
-using namespace android;
-
-static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) {
-    SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
-    int width, height;
-    if (NULL == decoder) {
-        doThrowIOE(env, "Image format not supported");
-        return nullObjectReturn("SkImageDecoder::Factory returned null");
-    }
-
-    JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true);
-    decoder->setAllocator(javaAllocator);
-    JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env);
-    decoder->setReporter(javaMemoryReporter);
-    javaAllocator->unref();
-    javaMemoryReporter->unref();
-
-    if (!decoder->buildTileIndex(stream, &width, &height, isShareable)) {
-        char msg[1024];
-        snprintf(msg, 1023, "Image failed to decode using %s decoder", decoder->getFormatName());
-        doThrowIOE(env, msg);
-        return nullObjectReturn("decoder->buildTileIndex returned false");
-    }
-
-    SkBitmapRegionDecoder *brd = new SkBitmapRegionDecoder(decoder, width, height);
-
-    return GraphicsJNI::createBitmapRegionDecoder(env, brd);
-}
-
-static jobject nativeNewInstanceFromByteArray(JNIEnv* env,
-        jobject, jbyteArray byteArray, int offset, int length,
-        jboolean isShareable) {
-    AutoJavaByteArray ar(env, byteArray);
-    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false);
-    SkAutoUnref aur(stream);
-    if (isShareable) {
-        aur.detach();
-    }
-    return doBuildTileIndex(env, stream, isShareable);
-}
-
-static jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env,
-        jobject clazz, jobject fileDescriptor, jboolean isShareable) {
-    NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
-
-    jint descriptor = env->GetIntField(fileDescriptor,
-                                       gFileDescriptor_descriptor);
-    bool weOwnTheFD = false;
-
-    if (isShareable) {
-        int newFD = ::dup(descriptor);
-        if (-1 != newFD) {
-            weOwnTheFD = true;
-            descriptor = newFD;
-        }
-    }
-
-    SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD);
-    SkAutoUnref aur(stream);
-    if (!stream->isValid()) {
-        return NULL;
-    }
-
-    if (isShareable) {
-        aur.detach();
-    }
-
-    // Restore our offset when we leave, so we can be called more than once
-    // with the same descriptor. This is only required if we didn't dup the
-    // file descriptor, but it is OK to do it all the time.
-    AutoFDSeek as(descriptor);
-
-    return doBuildTileIndex(env, stream, isShareable);
-}
-
-static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
-                                  jobject is,       // InputStream
-                                  jbyteArray storage, // byte[]
-                                  jboolean isShareable) {
-    jobject BitmapRegionDecoder = NULL;
-    SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
-
-    if (stream) {
-        // for now we don't allow shareable with java inputstreams
-        BitmapRegionDecoder = doBuildTileIndex(env, stream, false);
-        stream->unref();
-    }
-    return BitmapRegionDecoder;
-}
-
-static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
-                                 jint native_asset, // Asset
-                                 jboolean isShareable) {
-    SkStream* stream;
-    Asset* asset = reinterpret_cast<Asset*>(native_asset);
-    stream = new AssetStreamAdaptor(asset);
-    SkAutoUnref aur(stream);
-    if (isShareable) {
-        aur.detach();
-    }
-    return doBuildTileIndex(env, stream, isShareable);
-}
-
-/*
- * nine patch not supported
- *
- * purgeable not supported
- * reportSizeToVM not supported
- */
-static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd,
-        int start_x, int start_y, int width, int height, jobject options) {
-    SkImageDecoder *decoder = brd->getDecoder();
-    int sampleSize = 1;
-    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
-    bool doDither = true;
-
-    if (NULL != options) {
-        sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
-        // initialize these, in case we fail later on
-        env->SetIntField(options, gOptions_widthFieldID, -1);
-        env->SetIntField(options, gOptions_heightFieldID, -1);
-        env->SetObjectField(options, gOptions_mimeFieldID, 0);
-
-        jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
-        prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
-        doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
-    }
-
-    decoder->setDitherImage(doDither);
-    SkBitmap*           bitmap = new SkBitmap;
-    SkAutoTDelete<SkBitmap>       adb(bitmap);
-    AutoDecoderCancel   adc(options, decoder);
-
-    // To fix the race condition in case "requestCancelDecode"
-    // happens earlier than AutoDecoderCancel object is added
-    // to the gAutoDecoderCancelMutex linked list.
-    if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
-        return nullObjectReturn("gOptions_mCancelID");;
-    }
-
-    SkIRect region;
-    region.fLeft = start_x;
-    region.fTop = start_y;
-    region.fRight = start_x + width;
-    region.fBottom = start_y + height;
-
-    if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) {
-        return nullObjectReturn("decoder->decodeRegion returned false");
-    }
-
-    // update options (if any)
-    if (NULL != options) {
-        env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
-        env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
-        // TODO: set the mimeType field with the data from the codec.
-        // but how to reuse a set of strings, rather than allocating new one
-        // each time?
-        env->SetObjectField(options, gOptions_mimeFieldID,
-                            getMimeTypeString(env, decoder->getFormat()));
-    }
-
-    // detach bitmap from its autotdeleter, since we want to own it now
-    adb.detach();
-
-    SkPixelRef* pr;
-    pr = bitmap->pixelRef();
-    // promise we will never change our pixels (great for sharing and pictures)
-    pr->setImmutable();
-    // now create the java bitmap
-    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
-}
-
-static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
-    return brd->getHeight();
-}
-
-static int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
-    return brd->getWidth();
-}
-
-static void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
-    delete brd;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include <android_runtime/AndroidRuntime.h>
-
-static JNINativeMethod gBitmapRegionDecoderMethods[] = {
-    {   "nativeDecodeRegion",
-        "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
-        (void*)nativeDecodeRegion},
-
-    {   "nativeGetHeight", "(I)I", (void*)nativeGetHeight},
-
-    {   "nativeGetWidth", "(I)I", (void*)nativeGetWidth},
-
-    {   "nativeClean", "(I)V", (void*)nativeClean},
-
-    {   "nativeNewInstance",
-        "([BIIZ)Landroid/graphics/BitmapRegionDecoder;",
-        (void*)nativeNewInstanceFromByteArray
-    },
-
-    {   "nativeNewInstance",
-        "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;",
-        (void*)nativeNewInstanceFromStream
-    },
-
-    {   "nativeNewInstance",
-        "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;",
-        (void*)nativeNewInstanceFromFileDescriptor
-    },
-
-    {   "nativeNewInstance",
-        "(IZ)Landroid/graphics/BitmapRegionDecoder;",
-        (void*)nativeNewInstanceFromAsset
-    },
-};
-
-#define kClassPathName  "android/graphics/BitmapRegionDecoder"
-
-int register_android_graphics_BitmapRegionDecoder(JNIEnv* env);
-int register_android_graphics_BitmapRegionDecoder(JNIEnv* env)
-{
-    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
-            gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods));
-}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index b520c30..578de6f 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -169,8 +169,8 @@
 static jclass   gBitmapConfig_class;
 static jfieldID gBitmapConfig_nativeInstanceID;
 
-static jclass   gBitmapRegionDecoder_class;
-static jmethodID gBitmapRegionDecoder_constructorMethodID;
+static jclass   gLargeBitmap_class;
+static jmethodID gLargeBitmap_constructorMethodID;
 
 static jclass   gCanvas_class;
 static jfieldID gCanvas_nativeInstanceID;
@@ -377,18 +377,17 @@
     }
     return obj;
 }
-
-jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap)
+jobject GraphicsJNI::createLargeBitmap(JNIEnv* env, SkLargeBitmap* bitmap)
 {
     SkASSERT(bitmap != NULL);
 
-    jobject obj = env->AllocObject(gBitmapRegionDecoder_class);
+    jobject obj = env->AllocObject(gLargeBitmap_class);
     if (hasException(env)) {
         obj = NULL;
         return obj;
     }
     if (obj) {
-        env->CallVoidMethod(obj, gBitmapRegionDecoder_constructorMethodID, (jint)bitmap);
+        env->CallVoidMethod(obj, gLargeBitmap_constructorMethodID, (jint)bitmap);
         if (hasException(env)) {
             obj = NULL;
         }
@@ -614,8 +613,8 @@
     gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
                                             "(IZ[BI)V");
 
-    gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
-    gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V");
+    gLargeBitmap_class = make_globalref(env, "android/graphics/LargeBitmap");
+    gLargeBitmap_constructorMethodID = env->GetMethodID(gLargeBitmap_class, "<init>", "(I)V");
 
     gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config");
     gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class,
@@ -655,3 +654,4 @@
 
     return 0;
 }
+
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index d0f9125..1a43a3e 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -4,7 +4,7 @@
 #include "SkPoint.h"
 #include "SkRect.h"
 #include "SkBitmap.h"
-#include "../images/SkBitmapRegionDecoder.h"
+#include "../images/SkLargeBitmap.h"
 #include "../images/SkImageDecoder.h"
 #include <jni.h>
 
@@ -56,7 +56,7 @@
     
     static jobject createRegion(JNIEnv* env, SkRegion* region);
 
-    static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
+    static jobject createLargeBitmap(JNIEnv* env, SkLargeBitmap* bitmap);
 
     /** Set a pixelref for the bitmap (needs setConfig to already be called)
         Returns true on success. If it returns false, then it failed, and the
@@ -181,3 +181,4 @@
     do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
 
 #endif
+
diff --git a/core/jni/android/graphics/LargeBitmap.cpp b/core/jni/android/graphics/LargeBitmap.cpp
new file mode 100644
index 0000000..4cf5dfa
--- /dev/null
+++ b/core/jni/android/graphics/LargeBitmap.cpp
@@ -0,0 +1,138 @@
+#define LOG_TAG "LargeBitmap"
+
+#include "SkBitmap.h"
+#include "SkImageEncoder.h"
+#include "SkColorPriv.h"
+#include "GraphicsJNI.h"
+#include "SkDither.h"
+#include "SkUnPreMultiply.h"
+#include "SkUtils.h"
+#include "SkTemplates.h"
+#include "SkPixelRef.h"
+#include "BitmapFactory.h"
+#include "AutoDecodeCancel.h"
+#include "SkLargeBitmap.h"
+
+#include <binder/Parcel.h>
+#include "android_util_Binder.h"
+#include "android_nio_utils.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+#include <jni.h>
+
+#if 0
+    #define TRACE_BITMAP(code)  code
+#else
+    #define TRACE_BITMAP(code)
+#endif
+
+static jobject nullObjectReturn(const char msg[]) {
+    if (msg) {
+        SkDebugf("--- %s\n", msg);
+    }
+    return NULL;
+}
+
+/*
+ * nine patch not supported
+ *
+ * purgeable not supported
+ * reportSizeToVM not supported
+ */
+static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkLargeBitmap *bm,
+        int start_x, int start_y, int width, int height, jobject options) {
+    SkImageDecoder *decoder = bm->getDecoder();
+    int sampleSize = 1;
+    SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
+    bool doDither = true;
+
+    if (NULL != options) {
+        sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
+        // initialize these, in case we fail later on
+        env->SetIntField(options, gOptions_widthFieldID, -1);
+        env->SetIntField(options, gOptions_heightFieldID, -1);
+        env->SetObjectField(options, gOptions_mimeFieldID, 0);
+
+        jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
+        prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
+        doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
+    }
+
+    decoder->setDitherImage(doDither);
+    SkBitmap*           bitmap = new SkBitmap;
+    SkAutoTDelete<SkBitmap>       adb(bitmap);
+    AutoDecoderCancel   adc(options, decoder);
+
+    // To fix the race condition in case "requestCancelDecode"
+    // happens earlier than AutoDecoderCancel object is added
+    // to the gAutoDecoderCancelMutex linked list.
+    if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
+        return nullObjectReturn("gOptions_mCancelID");;
+    }
+
+    SkIRect region;
+    region.fLeft = start_x;
+    region.fTop = start_y;
+    region.fRight = start_x + width;
+    region.fBottom = start_y + height;
+
+    if (!bm->decodeRegion(bitmap, region, prefConfig, sampleSize)) {
+        return nullObjectReturn("decoder->decodeRegion returned false");
+    }
+
+    // update options (if any)
+    if (NULL != options) {
+        env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
+        env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
+        // TODO: set the mimeType field with the data from the codec.
+        // but how to reuse a set of strings, rather than allocating new one
+        // each time?
+        env->SetObjectField(options, gOptions_mimeFieldID,
+                            getMimeTypeString(env, decoder->getFormat()));
+    }
+
+    // detach bitmap from its autotdeleter, since we want to own it now
+    adb.detach();
+
+    SkPixelRef* pr;
+    pr = bitmap->pixelRef();
+    // promise we will never change our pixels (great for sharing and pictures)
+    pr->setImmutable();
+    // now create the java bitmap
+    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
+}
+
+static int nativeGetHeight(JNIEnv* env, jobject, SkLargeBitmap *bm) {
+    return bm->getHeight();
+}
+
+static int nativeGetWidth(JNIEnv* env, jobject, SkLargeBitmap *bm) {
+    return bm->getWidth();
+}
+
+static void nativeClean(JNIEnv* env, jobject, SkLargeBitmap *bm) {
+    delete bm;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <android_runtime/AndroidRuntime.h>
+
+static JNINativeMethod gLargeBitmapMethods[] = {
+    {   "nativeDecodeRegion",
+        "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
+        (void*)nativeDecodeRegion},
+    {   "nativeGetHeight", "(I)I", (void*)nativeGetHeight},
+    {   "nativeGetWidth", "(I)I", (void*)nativeGetWidth},
+    {   "nativeClean", "(I)V", (void*)nativeClean},
+};
+
+#define kClassPathName  "android/graphics/LargeBitmap"
+
+int register_android_graphics_LargeBitmap(JNIEnv* env);
+int register_android_graphics_LargeBitmap(JNIEnv* env)
+{
+    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
+                                gLargeBitmapMethods, SK_ARRAY_COUNT(gLargeBitmapMethods));
+}
+
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
deleted file mode 100644
index b6ead19..0000000
--- a/core/jni/android/graphics/Utils.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Utils.h"
-#include "SkUtils.h"
-
-using namespace android;
-
-bool AssetStreamAdaptor::rewind() {
-    off_t pos = fAsset->seek(0, SEEK_SET);
-    if (pos == (off_t)-1) {
-        SkDebugf("----- fAsset->seek(rewind) failed\n");
-        return false;
-    }
-    return true;
-}
-
-size_t AssetStreamAdaptor::read(void* buffer, size_t size) {
-    ssize_t amount;
-
-    if (NULL == buffer) {
-        if (0 == size) {  // caller is asking us for our total length
-            return fAsset->getLength();
-        }
-        // asset->seek returns new total offset
-        // we want to return amount that was skipped
-
-        off_t oldOffset = fAsset->seek(0, SEEK_CUR);
-        if (-1 == oldOffset) {
-            SkDebugf("---- fAsset->seek(oldOffset) failed\n");
-            return 0;
-        }
-        off_t newOffset = fAsset->seek(size, SEEK_CUR);
-        if (-1 == newOffset) {
-            SkDebugf("---- fAsset->seek(%d) failed\n", size);
-            return 0;
-        }
-        amount = newOffset - oldOffset;
-    } else {
-        amount = fAsset->read(buffer, size);
-        if (amount <= 0) {
-            SkDebugf("---- fAsset->read(%d) returned %d\n", size, amount);
-        }
-    }
-
-    if (amount < 0) {
-        amount = 0;
-    }
-    return amount;
-}
-
-jobject android::nullObjectReturn(const char msg[]) {
-    if (msg) {
-        SkDebugf("--- %s\n", msg);
-    }
-    return NULL;
-}
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
deleted file mode 100644
index 2de41a1..0000000
--- a/core/jni/android/graphics/Utils.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef UTILS_DEFINED
-#define UTILS_DEFINED
-
-#include "SkStream.h"
-
-#include "android_util_Binder.h"
-
-#include <jni.h>
-#include <utils/Asset.h>
-
-namespace android {
-
-class AssetStreamAdaptor : public SkStream {
-public:
-    AssetStreamAdaptor(Asset* a) : fAsset(a) {}
-    virtual bool rewind();
-    virtual size_t read(void* buffer, size_t size);
-
-private:
-    Asset*  fAsset;
-};
-
-
-/** Restore the file descriptor's offset in our destructor
- */
-class AutoFDSeek {
-public:
-    AutoFDSeek(int fd) : fFD(fd) {
-        fCurr = ::lseek(fd, 0, SEEK_CUR);
-    }
-    ~AutoFDSeek() {
-        if (fCurr >= 0) {
-            ::lseek(fFD, fCurr, SEEK_SET);
-        }
-    }
-private:
-    int     fFD;
-    off_t   fCurr;
-};
-
-jobject nullObjectReturn(const char msg[]);
-
-}; // namespace android
-
-#endif
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
deleted file mode 100644
index bc92b05..0000000
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/* Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import android.content.res.AssetManager;
-import android.os.MemoryFile;
-
-import java.io.BufferedInputStream;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * BitmapRegionDecoder can be used to decode a rectangle region from an image.
- * BitmapRegionDecoder is particularly useful when an original image is large and
- * you only need parts of the image.
- *
- * <p>To create a BitmapRegionDecoder, call newInstance(...).
- * Given a BitmapRegionDecoder, users can call decodeRegion() repeatedly
- * to get a decoded Bitmap of the specified region.
- *
- * @hide
- */
-public final class BitmapRegionDecoder {
-    private int mNativeBitmapRegionDecoder;
-    private boolean mRecycled;
-
-    /**
-     * Create a BitmapRegionDecoder from the specified byte array.
-     * Currently only the Jpeg format is supported.
-     *
-     * @param data byte array of compressed image data.
-     * @param offset offset into data for where the decoder should begin
-     *               parsing.
-     * @param length the number of bytes, beginning at offset, to parse
-     * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
-     *                    shallow reference to the input. If this is false,
-     *                    then the BitmapRegionDecoder will explicitly make a copy of the
-     *                    input data, and keep that. Even if sharing is allowed,
-     *                    the implementation may still decide to make a deep
-     *                    copy of the input data. If an image is progressively encoded,
-     *                    allowing sharing may degrade the decoding speed.
-     * @return BitmapRegionDecoder, or null if the image data could not be decoded.
-     * @throws IOException if the image format is not supported or can not be decoded.
-     */
-    public static BitmapRegionDecoder newInstance(byte[] data,
-            int offset, int length, boolean isShareable) throws IOException {
-        if ((offset | length) < 0 || data.length < offset + length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        return nativeNewInstance(data, offset, length, isShareable);
-    }
-
-    /**
-     * Create a BitmapRegionDecoder from the file descriptor.
-     * The position within the descriptor will not be changed when
-     * this returns, so the descriptor can be used again as is.
-     * Currently only the Jpeg format is supported.
-     *
-     * @param fd The file descriptor containing the data to decode
-     * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
-     *                    shallow reference to the input. If this is false,
-     *                    then the BitmapRegionDecoder will explicitly make a copy of the
-     *                    input data, and keep that. Even if sharing is allowed,
-     *                    the implementation may still decide to make a deep
-     *                    copy of the input data. If an image is progressively encoded,
-     *                    allowing sharing may degrade the decoding speed.
-     * @return BitmapRegionDecoder, or null if the image data could not be decoded.
-     * @throws IOException if the image format is not supported or can not be decoded.
-     */
-    public static BitmapRegionDecoder newInstance(
-            FileDescriptor fd, boolean isShareable) throws IOException {
-        if (MemoryFile.isMemoryFile(fd)) {
-            int mappedlength = MemoryFile.getSize(fd);
-            MemoryFile file = new MemoryFile(fd, mappedlength, "r");
-            InputStream is = file.getInputStream();
-            return newInstance(is, isShareable);
-        }
-        return nativeNewInstance(fd, isShareable);
-    }
-
-    /**
-     * Create a BitmapRegionDecoder from an input stream.
-     * The stream's position will be where ever it was after the encoded data
-     * was read.
-     * Currently only the Jpeg format is supported.
-     *
-     * @param is The input stream that holds the raw data to be decoded into a
-     *           BitmapRegionDecoder.
-     * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
-     *                    shallow reference to the input. If this is false,
-     *                    then the BitmapRegionDecoder will explicitly make a copy of the
-     *                    input data, and keep that. Even if sharing is allowed,
-     *                    the implementation may still decide to make a deep
-     *                    copy of the input data. If an image is progressively encoded,
-     *                    allowing sharing may degrade the decoding speed.
-     * @return BitmapRegionDecoder, or null if the image data could not be decoded.
-     * @throws IOException if the image format is not supported or can not be decoded.
-     */
-    public static BitmapRegionDecoder newInstance(InputStream is,
-            boolean isShareable) throws IOException {
-        // we need mark/reset to work properly in JNI
-
-        if (!is.markSupported()) {
-            is = new BufferedInputStream(is, 16 * 1024);
-        }
-
-        if (is instanceof AssetManager.AssetInputStream) {
-            return nativeNewInstance(
-                    ((AssetManager.AssetInputStream) is).getAssetInt(),
-                    isShareable);
-        } else {
-            // pass some temp storage down to the native code. 1024 is made up,
-            // but should be large enough to avoid too many small calls back
-            // into is.read(...).
-            byte [] tempStorage = new byte[16 * 1024];
-            return nativeNewInstance(is, tempStorage, isShareable);
-        }
-    }
-
-    /**
-     * Create a BitmapRegionDecoder from a file path.
-     * Currently only the Jpeg format is supported.
-     *
-     * @param pathName complete path name for the file to be decoded.
-     * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
-     *                    shallow reference to the input. If this is false,
-     *                    then the BitmapRegionDecoder will explicitly make a copy of the
-     *                    input data, and keep that. Even if sharing is allowed,
-     *                    the implementation may still decide to make a deep
-     *                    copy of the input data. If an image is progressively encoded,
-     *                    allowing sharing may degrade the decoding speed.
-     * @return BitmapRegionDecoder, or null if the image data could not be decoded.
-     * @throws IOException if the image format is not supported or can not be decoded.
-     */
-    public static BitmapRegionDecoder newInstance(String pathName,
-            boolean isShareable) throws IOException {
-        BitmapRegionDecoder decoder = null;
-        InputStream stream = null;
-
-        try {
-            stream = new FileInputStream(pathName);
-            decoder = newInstance(stream, isShareable);
-        } finally {
-            if (stream != null) {
-                try {
-                    stream.close();
-                } catch (IOException e) {
-                    // do nothing here
-                }
-            }
-        }
-        return decoder;
-    }
-
-    /*  Private constructor that must receive an already allocated native
-        region decoder int (pointer).
-
-        This can be called from JNI code.
-    */
-    private BitmapRegionDecoder(int decoder) {
-        mNativeBitmapRegionDecoder = decoder;
-        mRecycled = false;
-    }
-
-    /**
-     * Decodes a rectangle region in the image specified by rect.
-     *
-     * @param rect The rectangle that specified the region to be decode.
-     * @param options null-ok; Options that control downsampling.
-     *             inPurgeable is not supported.
-     * @return The decoded bitmap, or null if the image data could not be
-     *         decoded.
-     */
-    public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
-        checkRecycled("decodeRegion called on recycled region decoder");
-        if (rect.left < 0 || rect.top < 0 || rect.right > getWidth()
-                || rect.bottom > getHeight())
-            throw new IllegalArgumentException("rectangle is not inside the image");
-        return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
-                rect.right - rect.left, rect.bottom - rect.top, options);
-    }
-
-    /** Returns the original image's width */
-    public int getWidth() {
-        checkRecycled("getWidth called on recycled region decoder");
-        return nativeGetWidth(mNativeBitmapRegionDecoder);
-    }
-
-    /** Returns the original image's height */
-    public int getHeight() {
-        checkRecycled("getHeight called on recycled region decoder");
-        return nativeGetHeight(mNativeBitmapRegionDecoder);
-    }
-
-    /**
-     * Frees up the memory associated with this region decoder, and mark the
-     * region decoder as "dead", meaning it will throw an exception if decodeRegion(),
-     * getWidth() or getHeight() is called.
-     *
-     * <p>This operation cannot be reversed, so it should only be called if you are
-     * sure there are no further uses for the region decoder. This is an advanced call,
-     * and normally need not be called, since the normal GC process will free up this
-     * memory when there are no more references to this region decoder.
-     */
-    public void recycle() {
-        if (!mRecycled) {
-            nativeClean(mNativeBitmapRegionDecoder);
-            mRecycled = true;
-        }
-    }
-
-    /**
-     * Returns true if this region decoder has been recycled.
-     * If so, then it is an error to try use its method.
-     *
-     * @return true if the region decoder has been recycled
-     */
-    public final boolean isRecycled() {
-        return mRecycled;
-    }
-
-    /**
-     * Called by methods that want to throw an exception if the region decoder
-     * has already been recycled.
-     */
-    private void checkRecycled(String errorMessage) {
-        if (mRecycled) {
-            throw new IllegalStateException(errorMessage);
-        }
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            recycle();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private static native Bitmap nativeDecodeRegion(int lbm,
-            int start_x, int start_y, int width, int height,
-            BitmapFactory.Options options);
-    private static native int nativeGetWidth(int lbm);
-    private static native int nativeGetHeight(int lbm);
-    private static native void nativeClean(int lbm);
-
-    private static native BitmapRegionDecoder nativeNewInstance(
-            byte[] data, int offset, int length, boolean isShareable);
-    private static native BitmapRegionDecoder nativeNewInstance(
-            FileDescriptor fd, boolean isShareable);
-    private static native BitmapRegionDecoder nativeNewInstance(
-            InputStream is, byte[] storage, boolean isShareable);
-    private static native BitmapRegionDecoder nativeNewInstance(
-            int asset, boolean isShareable);
-}