Remove calls to deprecated SkBitmap::setIsOpaque()

setIsOpaque() has been removed from ToT Skia.

Update setters for mIsPremultiplied and hasAlpha to take the
other into consideration.

Change-Id: I1b36b0b0ce7126031eb7b769b563c17dcd4b306a
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 094129b..2125763 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -442,9 +442,15 @@
     return !bitmap->isOpaque();

 }

 

-static void Bitmap_setHasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap,

-                               jboolean hasAlpha) {

-    bitmap->setIsOpaque(!hasAlpha);

+static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, SkBitmap* bitmap,

+                                            jboolean hasAlpha, jboolean isPremul) {

+    if (!hasAlpha) {

+        bitmap->setAlphaType(kOpaque_SkAlphaType);

+    } else if (isPremul) {

+        bitmap->setAlphaType(kPremul_SkAlphaType);

+    } else {

+        bitmap->setAlphaType(kUnpremul_SkAlphaType);

+    }

 }

 

 static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap) {

@@ -770,7 +776,7 @@
     {   "nativeRowBytes",           "(I)I", (void*)Bitmap_rowBytes },

     {   "nativeConfig",             "(I)I", (void*)Bitmap_config },

     {   "nativeHasAlpha",           "(I)Z", (void*)Bitmap_hasAlpha },

-    {   "nativeSetHasAlpha",        "(IZ)V", (void*)Bitmap_setHasAlpha },

+    {   "nativeSetAlphaAndPremultiplied", "(IZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},

     {   "nativeHasMipMap",          "(I)Z", (void*)Bitmap_hasMipMap },

     {   "nativeSetHasMipMap",       "(IZ)V", (void*)Bitmap_setHasMipMap },

     {   "nativeCreateFromParcel",

diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 944b732..efa8ce7 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -401,8 +401,11 @@
 
         // TODO: avoid copying when scaled size equals decodingBitmap size
         SkBitmap::Config config = configForScaledOutput(decodingBitmap.config());
-        outputBitmap->setConfig(config, scaledWidth, scaledHeight);
-        outputBitmap->setIsOpaque(decodingBitmap.isOpaque());
+        // FIXME: If the alphaType is kUnpremul and the image has alpha, the
+        // colors may not be correct, since Skia does not yet support drawing
+        // to/from unpremultiplied bitmaps.
+        outputBitmap->setConfig(config, scaledWidth, scaledHeight, 0,
+                                decodingBitmap.alphaType());
         if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
             return nullObjectReturn("allocation failed for scaled bitmap");
         }
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 38a9ba3..c5c0eee 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -352,6 +352,18 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 
+// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
+static void assert_premultiplied(const SkBitmap& bitmap, bool isPremultiplied) {
+    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
+    // irrelevant. This just tests to ensure that the SkAlphaType is not
+    // opposite of isPremultiplied.
+    if (isPremultiplied) {
+        SkASSERT(bitmap.alphaType() != kUnpremul_SkAlphaType);
+    } else {
+        SkASSERT(bitmap.alphaType() != kPremul_SkAlphaType);
+    }
+}
+
 jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
         int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density)
 {
@@ -360,6 +372,10 @@
     bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
     bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
 
+    // The caller needs to have already set the alpha type properly, so the
+    // native SkBitmap stays in sync with the Java Bitmap.
+    assert_premultiplied(*bitmap, isPremultiplied);
+
     jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
             static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), buffer,
             bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied,
@@ -377,6 +393,10 @@
 void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
         bool isPremultiplied)
 {
+    // The caller needs to have already set the alpha type properly, so the
+    // native SkBitmap stays in sync with the Java Bitmap.
+    assert_premultiplied(*bitmap, isPremultiplied);
+
     env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
             bitmap->width(), bitmap->height(), isPremultiplied);
 }
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index f4590b9..5f29604 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -57,6 +57,7 @@
 
     /** Create a java Bitmap object given the native bitmap (required) and optional
         storage array (may be null).
+        bitmap's SkAlphaType must already be in sync with bitmapCreateFlags.
     */
     static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
             int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density = -1);
@@ -64,6 +65,9 @@
     static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
             jbyteArray ninepatch, int density = -1);
 
+    /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
+        sync with isPremultiplied
+    */
     static void reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
             bool isPremultiplied);
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 1868469..dd178d8 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -39,6 +39,7 @@
 
 #include <SkCanvas.h>
 #include <SkBitmap.h>
+#include <SkImage.h>
 #include <SkRegion.h>
 
 #include <utils/misc.h>
@@ -178,7 +179,8 @@
 static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
     /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
         we can map to SkBitmap::kARGB_8888_Config, and optionally call
-        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
+        bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
+        (as an accelerator)
     */
     switch (format) {
     case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
@@ -234,7 +236,7 @@
     ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
     bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);
     if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
-        bitmap.setIsOpaque(true);
+        bitmap.setAlphaType(kOpaque_SkAlphaType);
     }
     if (outBuffer.width > 0 && outBuffer.height > 0) {
         bitmap.setPixels(outBuffer.bits);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 67eade8..12acfe1 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -150,7 +150,8 @@
 static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
     /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
         we can map to SkBitmap::kARGB_8888_Config, and optionally call
-        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
+        bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
+        (as an accelerator)
     */
     switch (format) {
     case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
@@ -183,7 +184,7 @@
     SkBitmap* bitmap = new SkBitmap();
     bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
     if (f == PIXEL_FORMAT_RGBX_8888) {
-        bitmap->setIsOpaque(true);
+        bitmap->setAlphaType(kOpaque_SkAlphaType);
     }
 
     if (w > 0 && h > 0) {
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 0f429005..7a4a20a 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -27,6 +27,7 @@
 
 #include <SkBitmap.h>
 #include <SkCanvas.h>
+#include <SkImage.h>
 
 namespace android {
 
@@ -156,7 +157,7 @@
     bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount);
 
     if (buffer.format == WINDOW_FORMAT_RGBX_8888) {
-        bitmap.setIsOpaque(true);
+        bitmap.setAlphaType(kOpaque_SkAlphaType);
     }
 
     if (buffer.width > 0 && buffer.height > 0) {
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 3c24683..4d82264 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -67,6 +67,16 @@
      * setPremultiplied() aren't order dependent, despite being setters.
      */
     private boolean mIsPremultiplied;
+
+    /**
+     * Whether the Bitmap's content is expected to have alpha. Note that hasAlpha()
+     * does not directly return this value, because hasAlpha() may never return true
+     * for a 565 Bitmap.
+     *
+     * Any time this or mIsPremultiplied is changed, both are passed to native so they
+     * are not order dependent.
+     */
+    private boolean mHasAlpha;
     private byte[] mNinePatchChunk;   // may be null
     private int[] mLayoutBounds;   // may be null
     private int mWidth;
@@ -554,7 +564,7 @@
         checkRecycled("Can't copy a recycled bitmap");
         Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
         if (b != null) {
-            b.mIsPremultiplied = mIsPremultiplied;
+            b.setAlphaAndPremultiplied(mHasAlpha, mIsPremultiplied);
             b.mDensity = mDensity;
         }
         return b;
@@ -727,12 +737,12 @@
                 paint.setAntiAlias(true);
             }
         }
-        
+
         // The new bitmap was created from a known bitmap source so assume that
         // they use the same density
         bitmap.mDensity = source.mDensity;
-        bitmap.mIsPremultiplied = source.mIsPremultiplied;
-        
+        bitmap.setAlphaAndPremultiplied(source.mHasAlpha, source.mIsPremultiplied);
+
         canvas.setBitmap(bitmap);
         canvas.drawBitmap(source, srcR, dstR, paint);
         canvas.setBitmap(null);
@@ -810,9 +820,9 @@
         if (display != null) {
             bm.mDensity = display.densityDpi;
         }
+        bm.setHasAlpha(hasAlpha);
         if (config == Config.ARGB_8888 && !hasAlpha) {
             nativeErase(bm.mNativeBitmap, 0xff000000);
-            nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha);
         }
         // No need to initialize the bitmap to zeroes with other configs;
         // it is backed by a VM byte array which is by definition preinitialized
@@ -884,6 +894,7 @@
         if (display != null) {
             bm.mDensity = display.densityDpi;
         }
+        bm.mHasAlpha = true;
         return bm;
     }
 
@@ -1041,11 +1052,24 @@
      * <p>This method will not affect the behavior of a bitmap without an alpha
      * channel, or if {@link #hasAlpha()} returns false.</p>
      *
+     * <p>Calling {@link createBitmap()} or {@link createScaledBitmap()} with a source
+     * Bitmap whose colors are not pre-multiplied may result in a RuntimeException,
+     * since those functions require drawing the source, which is not supported for
+     * un-pre-multiplied Bitmaps.</p>
+     *
      * @see Bitmap#isPremultiplied()
      * @see BitmapFactory.Options#inPremultiplied
      */
     public final void setPremultiplied(boolean premultiplied) {
         mIsPremultiplied = premultiplied;
+        nativeSetAlphaAndPremultiplied(mNativeBitmap, mHasAlpha, premultiplied);
+    }
+
+    /** Helper function to set both alpha and premultiplied. **/
+    private final void setAlphaAndPremultiplied(boolean hasAlpha, boolean premultiplied) {
+        mHasAlpha = hasAlpha;
+        mIsPremultiplied = premultiplied;
+        nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha, premultiplied);
     }
 
     /** Returns the bitmap's width */
@@ -1206,7 +1230,8 @@
      * non-opaque per-pixel alpha values.
      */
     public void setHasAlpha(boolean hasAlpha) {
-        nativeSetHasAlpha(mNativeBitmap, hasAlpha);
+        mHasAlpha = hasAlpha;
+        nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha, mIsPremultiplied);
     }
 
     /**
@@ -1611,7 +1636,8 @@
 
     private static native void nativePrepareToDraw(int nativeBitmap);
     private static native boolean nativeHasAlpha(int nativeBitmap);
-    private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha);
+    private static native void nativeSetAlphaAndPremultiplied(int nBitmap, boolean hasAlpha,
+                                                              boolean isPremul);
     private static native boolean nativeHasMipMap(int nativeBitmap);
     private static native void nativeSetHasMipMap(int nBitmap, boolean hasMipMap);
     private static native boolean nativeSameAs(int nb0, int nb1);
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index b714fab..2b69a15 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -153,8 +153,12 @@
          *
          * <p>This does not affect bitmaps without an alpha channel.</p>
          *
+         * <p>Setting this flag to false while setting {@link #inScaled} to true
+         * may result in incorrect colors.</p>
+         *
          * @see Bitmap#hasAlpha()
          * @see Bitmap#isPremultiplied()
+         * @see #inScaled
          */
         public boolean inPremultiplied;
 
@@ -249,6 +253,9 @@
          * <p>This flag is turned on by default and should be turned off if you need
          * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this
          * flag and are always scaled.
+         *
+         * <p>If {@link #inPremultiplied} is set to false, and the image has alpha,
+         * setting this flag to true may result in incorrect colors.
          */
         public boolean inScaled;
 
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 457ca59..467f6ca 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -285,10 +285,9 @@
 void TextureCache::uploadLoFiTexture(bool resize, const SkBitmap* bitmap,
         uint32_t width, uint32_t height) {
     SkBitmap rgbaBitmap;
-    rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+    rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0, bitmap->alphaType());
     rgbaBitmap.allocPixels();
     rgbaBitmap.eraseColor(0);
-    rgbaBitmap.setIsOpaque(bitmap->isOpaque());
 
     SkCanvas canvas(rgbaBitmap);
     canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL);
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index 6424744..53f04bc 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -30,6 +30,7 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <SkImage.h>
 #include <SkMallocPixelRef.h>
 
 #include "omx_jpeg_decoder.h"
@@ -184,8 +185,7 @@
 
 void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
         int width, int height) {
-    bm->setConfig(getColorSpaceConfig(pref), width, height);
-    bm->setIsOpaque(true);
+    bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
 }
 
 SkBitmap::Config OmxJpegImageDecoder::getColorSpaceConfig(