In Bitmap.reconfigure, update the pixelref's info.

This fixes CTS tests which are crashing on an SkASSERT due to a
mismatch of SkImageInfo between the SkPixelRef and SkBitmap.

Also directly call ref() and unref() instead of SkSafeRef/SkSafeUnref,
since we would already crash if the SkPixelRef in question was NULL.

Also if the user attempts to reconfigure to 4444, use 8888 instead.

Change-Id: I473ef225c6cd1c92d67ae103c53c6cff0dad92de
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 0328517..9998995 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -361,24 +361,50 @@
 }
 
 static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
-        jint width, jint height, jint configHandle, jint allocSize) {
+        jint width, jint height, jint configHandle, jint allocSize,
+        jboolean requestPremul) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
-    if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {
+    SkColorType colorType = SkBitmapConfigToColorType(config);
+
+    // ARGB_4444 is a deprecated format, convert automatically to 8888
+    if (colorType == kARGB_4444_SkColorType) {
+        colorType = kN32_SkColorType;
+    }
+
+    if (width * height * SkColorTypeBytesPerPixel(colorType) > allocSize) {
         // done in native as there's no way to get BytesPerPixel in Java
         doThrowIAE(env, "Bitmap not large enough to support new configuration");
         return;
     }
     SkPixelRef* ref = bitmap->pixelRef();
-    SkSafeRef(ref);
-    bitmap->setConfig(config, width, height);
+    ref->ref();
+    SkAlphaType alphaType;
+    if (bitmap->colorType() != kRGB_565_SkColorType
+            && bitmap->alphaType() == kOpaque_SkAlphaType) {
+        // If the original bitmap was set to opaque, keep that setting, unless it
+        // was 565, which is required to be opaque.
+        alphaType = kOpaque_SkAlphaType;
+    } else {
+        // Otherwise respect the premultiplied request.
+        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+    }
+    bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType));
+    // FIXME: Skia thinks of an SkPixelRef as having a constant SkImageInfo (except for
+    // its alphatype), so it would make more sense from Skia's perspective to create a
+    // new SkPixelRef. That said, libhwui uses the pointer to the SkPixelRef as a key
+    // for its cache, so it won't realize this is the same Java Bitmap.
+    SkImageInfo& info = const_cast<SkImageInfo&>(ref->info());
+    // Use the updated from the SkBitmap, which may have corrected an invalid alphatype.
+    // (e.g. 565 non-opaque)
+    info = bitmap->info();
     bitmap->setPixelRef(ref);
 
     // notifyPixelsChanged will increment the generation ID even though the actual pixel data
     // hasn't been touched. This signals the renderer that the bitmap (including width, height,
-    // and config) has changed.
+    // colortype and alphatype) has changed.
     ref->notifyPixelsChanged();
-    SkSafeUnref(ref);
+    ref->unref();
 }
 
 // These must match the int values in Bitmap.java
@@ -799,7 +825,7 @@
         (void*)Bitmap_copy },
     {   "nativeDestructor",         "(J)V", (void*)Bitmap_destructor },
     {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
-    {   "nativeReconfigure",        "(JIIII)V", (void*)Bitmap_reconfigure },
+    {   "nativeReconfigure",        "(JIIIIZ)V", (void*)Bitmap_reconfigure },
     {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
         (void*)Bitmap_compress },
     {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 06cf253..ef0a411 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -194,6 +194,11 @@
      * while {@link #getAllocationByteCount()} will reflect that of the initial
      * configuration.</p>
      *
+     * <p>Note: This may change this result of hasAlpha(). When converting to 565,
+     * the new bitmap will always be considered opaque. When converting from 565,
+     * the new bitmap will be considered non-opaque, and will respect the value
+     * set by setPremultiplied().</p>
+     *
      * <p>WARNING: This method should NOT be called on a bitmap currently used
      * by the view system. It does not make guarantees about how the underlying
      * pixel buffer is remapped to the new config, just that the allocation is
@@ -217,7 +222,8 @@
             throw new IllegalStateException("native-backed bitmaps may not be reconfigured");
         }
 
-        nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length);
+        nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length,
+                mIsPremultiplied);
         mWidth = width;
         mHeight = height;
     }
@@ -1586,7 +1592,8 @@
     private static native void nativeDestructor(long nativeBitmap);
     private static native boolean nativeRecycle(long nativeBitmap);
     private static native void nativeReconfigure(long nativeBitmap, int width, int height,
-                                                 int config, int allocSize);
+                                                 int config, int allocSize,
+                                                 boolean isPremultiplied);
 
     private static native boolean nativeCompress(long nativeBitmap, int format,
                                             int quality, OutputStream stream,