Uploaded image for project: 'Appcelerator - INBOX'
  1. Appcelerator - INBOX
  2. AC-2920

FC when recycling a "Bitmap.createScaledBitmap" with the same size os the original Bitmap

    Details

      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

      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

      TiDrawableReference.java

      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

      TiDrawableReference.java

          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.

        Attachments

          Activity

            People

            • Assignee:
              anagesh Anirudh Nagesh
              Reporter:
              luciofm Lúcio Fernando Maciel
            • Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Git Source Code