Merge "Rename onException to onPartialImage"
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index c237564..ec03f82 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -46,7 +46,7 @@
 static jmethodID gPoint_constructorMethodID;
 static jmethodID gIncomplete_constructorMethodID;
 static jmethodID gCorrupt_constructorMethodID;
-static jmethodID gCallback_onExceptionMethodID;
+static jmethodID gCallback_onPartialImageMethodID;
 static jmethodID gPostProcess_postProcessMethodID;
 static jmethodID gCanvas_constructorMethodID;
 static jmethodID gCanvas_releaseMethodID;
@@ -276,7 +276,7 @@
     SkAndroidCodec::AndroidOptions options;
     options.fSampleSize = sampleSize;
     auto result = codec->getAndroidPixels(decodeInfo, bm.getPixels(), bm.rowBytes(), &options);
-    jobject jexception = env->ExceptionOccurred();
+    jthrowable jexception = env->ExceptionOccurred();
     if (jexception) {
         env->ExceptionClear();
     }
@@ -287,12 +287,14 @@
             break;
         case SkCodec::kIncompleteInput:
             if (jcallback && !jexception) {
-                jexception = env->NewObject(gIncomplete_class, gIncomplete_constructorMethodID);
+                jexception = (jthrowable) env->NewObject(gIncomplete_class,
+                                                         gIncomplete_constructorMethodID);
             }
             break;
         case SkCodec::kErrorInInput:
             if (jcallback && !jexception) {
-                jexception = env->NewObject(gCorrupt_class, gCorrupt_constructorMethodID);
+                jexception = (jthrowable) env->NewObject(gCorrupt_class,
+                                                         gCorrupt_constructorMethodID);
             }
             break;
         default:
@@ -303,9 +305,14 @@
     }
 
     if (jexception) {
-        // FIXME: Do not provide a way for the client to force the method to return null.
-        if (!env->CallBooleanMethod(jcallback, gCallback_onExceptionMethodID, jexception) ||
-            env->ExceptionCheck()) {
+        bool throwException = !env->CallBooleanMethod(jcallback, gCallback_onPartialImageMethodID,
+                                                      jexception);
+        if (env->ExceptionCheck()) {
+            return nullptr;
+        }
+
+        if (throwException) {
+            env->Throw(jexception);
             return nullptr;
         }
     }
@@ -512,7 +519,7 @@
     { "nCreate",        "([BII)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
     { "nCreate",        "(Ljava/io/InputStream;[B)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream },
     { "nCreate",        "(Ljava/io/FileDescriptor;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
-    { "nDecodeBitmap",  "(JLandroid/graphics/ImageDecoder$OnExceptionListener;Landroid/graphics/PostProcess;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;",
+    { "nDecodeBitmap",  "(JLandroid/graphics/ImageDecoder$OnPartialImageListener;Landroid/graphics/PostProcess;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;",
                                                                  (void*) ImageDecoder_nDecodeBitmap },
     { "nGetSampledSize","(JI)Landroid/graphics/Point;",          (void*) ImageDecoder_nGetSampledSize },
     { "nGetPadding",    "(JLandroid/graphics/Rect;)V",           (void*) ImageDecoder_nGetPadding },
@@ -533,8 +540,8 @@
     gCorrupt_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder$CorruptException"));
     gCorrupt_constructorMethodID = GetMethodIDOrDie(env, gCorrupt_class, "<init>", "()V");
 
-    jclass callback_class = FindClassOrDie(env, "android/graphics/ImageDecoder$OnExceptionListener");
-    gCallback_onExceptionMethodID = GetMethodIDOrDie(env, callback_class, "onException", "(Ljava/io/IOException;)Z");
+    jclass callback_class = FindClassOrDie(env, "android/graphics/ImageDecoder$OnPartialImageListener");
+    gCallback_onPartialImageMethodID = GetMethodIDOrDie(env, callback_class, "onPartialImage", "(Ljava/io/IOException;)Z");
 
     jclass postProcess_class = FindClassOrDie(env, "android/graphics/PostProcess");
     gPostProcess_postProcessMethodID = GetMethodIDOrDie(env, postProcess_class, "postProcess", "(Landroid/graphics/Canvas;II)I");
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 94b219a..419e2b7 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -239,7 +239,7 @@
     };
 
     /**
-     *  Supplied to onException if the provided data is incomplete.
+     *  Supplied to onPartialImage if the provided data is incomplete.
      *
      *  Will never be thrown by ImageDecoder.
      *
@@ -252,7 +252,7 @@
      *
      *  May be thrown if there is nothing to display.
      *
-     *  If supplied to onException, there may be a correct partial image to
+     *  If supplied to onPartialImage, there may be a correct partial image to
      *  display.
      */
     public static class CorruptException extends IOException {};
@@ -275,17 +275,21 @@
     /**
      *  Optional listener supplied to the ImageDecoder.
      */
-    public static interface OnExceptionListener {
+    public static interface OnPartialImageListener {
         /**
-         *  Called when there is a problem in the stream or in the data.
-         *  FIXME: Report how much of the image has been decoded?
+         *  Called when there is only a partial image to display.
          *
-         *  @param e IOException containing information about the error.
-         *  @return True to create and return a {@link Drawable}/
-         *      {@link Bitmap} with partial data. False to return
-         *      {@code null}. True is the default.
+         *  If the input is incomplete or contains an error, this listener lets
+         *  the client know that and allows them to optionally bypass the rest
+         *  of the decode/creation process.
+         *
+         *  @param e IOException containing information about the error that
+         *      interrupted the decode.
+         *  @return True (which is the default) to create and return a
+         *      {@link Drawable}/{@link Bitmap} with partial data. False to
+         *      abort the decode and throw the {@link java.io.IOException}.
          */
-        public boolean onException(IOException e);
+        public boolean onPartialImage(IOException e);
     };
 
     // Fields
@@ -302,8 +306,8 @@
     private boolean mAsAlphaMask = false;
     private Rect    mCropRect;
 
-    private PostProcess         mPostProcess;
-    private OnExceptionListener mOnExceptionListener;
+    private PostProcess            mPostProcess;
+    private OnPartialImageListener mOnPartialImageListener;
 
     // Objects for interacting with the input.
     private InputStream         mInputStream;
@@ -557,13 +561,13 @@
     }
 
     /**
-     *  Set (replace) the {@link OnExceptionListener} on this object.
+     *  Set (replace) the {@link OnPartialImageListener} on this object.
      *
      *  Will be called if there is an error in the input. Without one, a
      *  partial {@link Bitmap} will be created.
      */
-    public void setOnExceptionListener(OnExceptionListener l) {
-        mOnExceptionListener = l;
+    public void setOnPartialImageListener(OnPartialImageListener l) {
+        mOnPartialImageListener = l;
     }
 
     /**
@@ -712,7 +716,7 @@
             }
 
             Bitmap bm = nDecodeBitmap(decoder.mNativePtr,
-                                      decoder.mOnExceptionListener,
+                                      decoder.mOnPartialImageListener,
                                       decoder.mPostProcess,
                                       decoder.mDesiredWidth,
                                       decoder.mDesiredHeight,
@@ -722,13 +726,6 @@
                                       false,    // mRequireUnpremultiplied
                                       decoder.mPreferRamOverQuality,
                                       decoder.mAsAlphaMask);
-            if (bm == null) {
-                // FIXME: bm should never be null. Currently a return value
-                // of false from onException will result in bm being null. What
-                // is the right API to choose to discard partial Bitmaps?
-                return null;
-            }
-
             Resources res = src.getResources();
             if (res == null) {
                 bm.setDensity(Bitmap.DENSITY_NONE);
@@ -786,7 +783,7 @@
             decoder.checkState();
 
             return nDecodeBitmap(decoder.mNativePtr,
-                                 decoder.mOnExceptionListener,
+                                 decoder.mOnPartialImageListener,
                                  decoder.mPostProcess,
                                  decoder.mDesiredWidth,
                                  decoder.mDesiredHeight,
@@ -821,7 +818,7 @@
     private static native ImageDecoder nCreate(FileDescriptor fd) throws IOException;
     @NonNull
     private static native Bitmap nDecodeBitmap(long nativePtr,
-            OnExceptionListener listener,
+            OnPartialImageListener listener,
             PostProcess postProcess,
             int width, int height,
             Rect cropRect, boolean mutable,