Import latest bitmap library changes.

Change-Id: Ic3a79a1154fb1329bf4c163ea6aeb32f8bd3857d
diff --git a/sample/BUILD b/sample/BUILD
index 13931e6..595790c 100644
--- a/sample/BUILD
+++ b/sample/BUILD
@@ -4,21 +4,34 @@
     ],
 )
 
+licenses(["notice"])  # Apache License 2.0
+
+exports_files(["LICENSE"])
+
 android_manifest_merge(
     name = "merged_manifest",
     srcs = ["AndroidManifest.xml"],
     deps = [
-        "//java/com/google/android/apps/bigtop/third_party/bitmap:AndroidManifest.xml",
+        "//third_party/java_src/android_libs/bitmap_library:AndroidManifest.xml",
     ],
 )
 
+filegroup(
+    name = "resource_files",
+    srcs = glob(
+        ["res/**"],
+        exclude_directories = 1,
+    ),
+)
+
 android_resources(
     name = "resources",
     custom_package = "com.example.bitmapsample",
     inline_constants = 0,
     manifest = ":merged_manifest",
-    resources = glob(["res/**"]) + [
-        "//java/com/google/android/apps/bigtop/third_party/bitmap:resource_files",
+    resources = [
+        ":resource_files",
+        "//third_party/java_src/android_libs/bitmap_library:resource_files",
     ],
     resources_dir = "res",
     visibility = ["//visibility:private"],
@@ -36,6 +49,6 @@
     ],
     resources = ":resources",
     deps = [
-        "//java/com/google/android/apps/bigtop/third_party/bitmap",
+        "//third_party/java_src/android_libs/bitmap_library",
     ],
 )
diff --git a/src/com/android/bitmap/RequestKey.java b/src/com/android/bitmap/RequestKey.java
index adf1d72..882c75b 100644
--- a/src/com/android/bitmap/RequestKey.java
+++ b/src/com/android/bitmap/RequestKey.java
@@ -117,7 +117,7 @@
          * the UI thread.
          * @param key The key that the FileDescriptorFactory was created for. The callback should
          *            check that the key has not changed.
-         * @param factory The FileDescriptorFactory to decode from.
+         * @param factory The FileDescriptorFactory to decode from. Pass null to cancel decode.
          */
         void fileDescriptorFactoryCreated(RequestKey key, FileDescriptorFactory factory);
     }
diff --git a/src/com/android/bitmap/drawable/BasicBitmapDrawable.java b/src/com/android/bitmap/drawable/BasicBitmapDrawable.java
index ffea5c8..5de0840 100644
--- a/src/com/android/bitmap/drawable/BasicBitmapDrawable.java
+++ b/src/com/android/bitmap/drawable/BasicBitmapDrawable.java
@@ -203,7 +203,7 @@
         }
 
         if (key == null) {
-            invalidateSelf();
+            onDecodeFailed();
             Trace.endSection();
             return;
         }
@@ -241,6 +241,7 @@
      */
     protected void loadFileDescriptorFactory() {
         if (mCurrKey == null || mDecodeWidth == 0 || mDecodeHeight == 0) {
+            onDecodeFailed();
             return;
         }
 
@@ -258,16 +259,30 @@
             final FileDescriptorFactory factory) {
         if (mCreateFileDescriptorFactoryTask == null) {
             // Cancelled.
+            onDecodeFailed();
             return;
         }
         mCreateFileDescriptorFactoryTask = null;
 
+        if (factory == null) {
+            // Failed.
+            onDecodeFailed();
+            return;
+        }
+
         if (key.equals(mCurrKey)) {
             decode(factory);
         }
     }
 
     /**
+     * Called when the decode process is cancelled at any time.
+     */
+    protected void onDecodeFailed() {
+        invalidateSelf();
+    }
+
+    /**
      * Should only be overriden, not called.
      */
     protected void decode(final FileDescriptorFactory factory) {
diff --git a/src/com/android/bitmap/drawable/CircularBitmapDrawable.java b/src/com/android/bitmap/drawable/CircularBitmapDrawable.java
index 942cbfb..cb8ede7 100644
--- a/src/com/android/bitmap/drawable/CircularBitmapDrawable.java
+++ b/src/com/android/bitmap/drawable/CircularBitmapDrawable.java
@@ -98,11 +98,21 @@
     @Override
     protected void onDrawPlaceholderOrProgress(final Canvas canvas,
             final TileDrawable drawable) {
-        BitmapDrawable placeholder = (BitmapDrawable) drawable.getInnerDrawable();
-        Bitmap bitmap = placeholder.getBitmap();
-        float alpha = placeholder.getPaint().getAlpha() / 255f;
-        sRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
-        onDrawCircularBitmap(bitmap, canvas, sRect, getBounds(), alpha);
+        Rect bounds = getBounds();
+        if (drawable.getInnerDrawable() instanceof BitmapDrawable) {
+            BitmapDrawable placeholder =
+                (BitmapDrawable) drawable.getInnerDrawable();
+            Bitmap bitmap = placeholder.getBitmap();
+            float alpha = placeholder.getPaint().getAlpha() / 255f;
+            sRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
+            onDrawCircularBitmap(bitmap, canvas, sRect, bounds, alpha);
+        } else {
+          super.onDrawPlaceholderOrProgress(canvas, drawable);
+        }
+
+        // Then draw the border.
+        canvas.drawCircle(bounds.centerX(), bounds.centerY(),
+                bounds.width() / 2f - mBorderWidth / 2, mBorderPaint);
     }
 
     /**
diff --git a/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java b/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java
index 0e01142..ab81e6f 100644
--- a/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java
+++ b/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java
@@ -55,7 +55,7 @@
     public static final int LOAD_STATE_FAILED = 4;
 
     public static final boolean DEBUG = false;
-    public static final String TAG = ExtendedBitmapDrawable.class.getSimpleName();
+    private static final String TAG = ExtendedBitmapDrawable.class.getSimpleName();
 
     private final Resources mResources;
     private final ExtendedOptions mOpts;
@@ -102,18 +102,20 @@
                 ConstantState constantState = mOpts.placeholder.getConstantState();
                 if (constantState != null) {
                     placeholder = constantState.newDrawable(mResources);
+                } else {
+                    placeholder = mOpts.placeholder;
+                }
 
-                    Rect bounds = mOpts.placeholder.getBounds();
-                    if (bounds.width() != 0) {
-                        placeholderWidth = bounds.width();
-                    } else if (placeholder.getIntrinsicWidth() != -1) {
-                        placeholderWidth = placeholder.getIntrinsicWidth();
-                    }
-                    if (bounds.height() != 0) {
-                        placeholderHeight = bounds.height();
-                    } else if (placeholder.getIntrinsicHeight() != -1) {
-                        placeholderHeight = placeholder.getIntrinsicHeight();
-                    }
+                Rect bounds = mOpts.placeholder.getBounds();
+                if (bounds.width() != 0) {
+                    placeholderWidth = bounds.width();
+                } else if (placeholder.getIntrinsicWidth() != -1) {
+                    placeholderWidth = placeholder.getIntrinsicWidth();
+                }
+                if (bounds.height() != 0) {
+                    placeholderHeight = bounds.height();
+                } else if (placeholder.getIntrinsicHeight() != -1) {
+                    placeholderHeight = placeholder.getIntrinsicHeight();
                 }
             }
 
@@ -198,7 +200,11 @@
 
     @Override
     protected void setBitmap(ReusableBitmap bmp) {
-        setLoadState((bmp != null) ? LOAD_STATE_LOADED : LOAD_STATE_FAILED);
+        if (bmp != null) {
+            setLoadState(LOAD_STATE_LOADED);
+        } else {
+            onDecodeFailed();
+        }
 
         super.setBitmap(bmp);
     }
@@ -217,6 +223,13 @@
         super.loadFileDescriptorFactory();
     }
 
+    @Override
+    protected void onDecodeFailed() {
+        super.onDecodeFailed();
+
+        setLoadState(LOAD_STATE_FAILED);
+    }
+
     protected boolean shouldExecuteStateChange() {
         // TODO: AttachmentDrawable should override this method to match prev and curr request keys.
         return /* opts.stateChanges */ true;
diff --git a/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java b/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java
index e23642d..953bfd0 100644
--- a/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java
+++ b/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java
@@ -24,6 +24,7 @@
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.util.Log;
 
 import com.android.bitmap.BitmapCache;
 
@@ -39,6 +40,7 @@
  * {@link #CORNER_STYLE_FLAP} corners have a colored flap drawn within the bounds.
  */
 public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
+    private static final String TAG = StyledCornersBitmapDrawable.class.getSimpleName();
 
     public static final int CORNER_STYLE_SHARP = 0;
     public static final int CORNER_STYLE_ROUND = 1;
@@ -66,6 +68,7 @@
     private int mScrimColor;
     private float mBorderWidth;
     private boolean mIsCompatibilityMode;
+    private boolean mEatInvalidates;
 
     /**
      * Create a new StyledCornersBitmapDrawable.
@@ -224,6 +227,8 @@
             return;
         }
 
+        pauseInvalidate();
+
         // Clip to path.
         if (!mIsCompatibilityMode) {
             canvas.save();
@@ -276,6 +281,17 @@
 
         // Draw border around path.
         canvas.drawPath(mClipPath, mBorderPaint);
+
+        resumeInvalidate();
+    }
+
+    @Override
+    public void invalidateSelf() {
+        if (!mEatInvalidates) {
+            super.invalidateSelf();
+        } else {
+            Log.d(TAG, "Skipping invalidate.");
+        }
     }
 
     protected void drawFakeCornersForCompatibilityMode(final Canvas canvas) {
@@ -362,6 +378,14 @@
         }
     }
 
+    private void pauseInvalidate() {
+        mEatInvalidates = true;
+    }
+
+    private void resumeInvalidate() {
+        mEatInvalidates = false;
+    }
+
     private void recalculatePath() {
         Rect bounds = getBounds();