[AC-2920] FC when recycling a "Bitmap.createScaledBitmap" with the same size os the original Bitmap
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | n/a |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2012-09-05T11:36:45.000+0000 |
Affected Version/s | n/a |
Fix Version/s | n/a |
Components | Titanium SDK & CLI |
Labels | android, crash, defect, release-2.1.0, release-2.2.0 |
Reporter | LĂșcio Fernando Maciel |
Assignee | Anirudh Nagesh |
Created | 2012-08-07T17:19:07.000+0000 |
Updated | 2016-03-08T07:47:54.000+0000 |
Description
Testing the BrazilJS conference App on Android, I caught a strange bug that only happens with a very specific configuration. We could only trigger the bug on a Galaxy Nexus running 4.1.1, but I don't really know which other devices/versions could be affected.
The code which triggered the bug is available at https://github.com/Nyvra/App-BrazilJS/blob/70a4e0c78ef9cc4e126043ef266b00e3138b92b4/Resources/android/ui/WinTalk.coffee
rowSpeaker.add(Ti.UI.createImageView({
left: "13dp",
width: "30dp",
height: "30dp",
image: "/images/speakers/detail/" + speaker_obj.picture
}));
This triggered a Force Close with the following backtrace:
E/TiApplication( 6391): (main) [61,13021] Sending event: exception on
thread: main msg:java.lang.IllegalArgumentException: Cannot draw
recycled bitmaps; Titanium 2.1.0,2012/06/28 12:16,6e3cab6
E/TiApplication( 6391): java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
E/TiApplication( 6391): at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:778)
E/TiApplication( 6391): at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:117)
E/TiApplication( 6391): at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)
E/TiApplication( 6391): at android.widget.ImageView.onDraw(ImageView.java:961)
E/TiApplication( 6391): at android.view.View.draw(View.java:13458)
E/TiApplication( 6391): at android.view.View.getDisplayList(View.java:12409)
E/TiApplication( 6391): at android.view.View.getDisplayList(View.java:12453)
E/TiApplication( 6391): at android.view.View.draw(View.java:13182)
E/TiApplication( 6391): at android.view.ViewGroup.drawChild(ViewGroup.java:2929)
E/TiApplication( 6391): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)
E/TiApplication( 6391): at android.view.View.getDisplayList(View.java:12407)
E/TiApplication( 6391): at android.view.View.getDisplayList(View.java:12453)
E/TiApplication( 6391): at android.view.View.draw(View.java:13182)
E/TiApplication( 6391): at android.view.ViewGroup.drawChild(ViewGroup.java:2929)
E/TiApplication( 6391): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)
E/TiApplication( 6391): at org.appcelerator.titanium.view.TiCompositeLayout.dispatchDraw(TiCompositeLayout.java:655)
The problem is that a recycled Bitmap is being used.
Studying the Titanium source code I've found a situation where TiDrawableReference.java getBitmap() function is recycling the returned Bitmap.
From the Android SDK documentation:
public static Bitmap createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)
Creates a new bitmap, scaled from an existing bitmap, when possible. If the specified width and height are the same as the current width and height of the source btimap, the source bitmap is returned and no new bitmap is created.
Returns
The new scaled bitmap or the source bitmap if no scaling is required.
getBitmap() calls
b = Bitmap.createScaledBitmap(bTemp, destWidth, destHeight, true);
So whenever the bTemp Bitmap has the same size as the scaled Bitmap, the Android framework will return the original Bitmap (bTemp in this case), and we will have both bTemp and b pointing to the same Bitmap.
Later in this function is called
if (bTemp != null) {
bTemp.recycle();
bTemp = null;
}
...
return b;
Which will recycle the bTemp bitmap, which is the same as b Bitmap which is returned in the function, causing the "Cannot draw recycled bitmaps"
I've created a fix for this, and will send a pull request.
Hi Lucio, Thanks for the pull request. But this issue has been fixed in the latest 2.1.2GA and 2.2.0 CI build. It was an issue specific to Android JellyBean. Regards, Anirudh
Resolved in 2.1.2GA and 2.2.0 CI