Tuesday, May 1, 2012

[android-developers] Rendering off UI thread causes ANR on Samsung Note

This TestActivity mimics some behavior in my app, which casues an ANR on the Samsung Note ( running Android version 2.3.6).  It did not produce an ANR on a few other devices I tried, including 2 different Samsung devices both with 2.3.6.

Based on the traces.txt file, the GUI thread appears to get stuck while painting an ImageButton.  No idea why this happens, but the traces.txt is pastebin-ed below.

The Activity creates a layout with a lot of ImageButtons, each of which will cause the entire layout to invalidate when pressed.  It then starts a new thread which renders a Bitmap into a canvas.  The Bitmap is painted into the canvas one line at a time, by using Canvas.drawBitmap(int[]....); the ANR occurs regardless of the pixel values of the Bitmap, so the test app just uses an instantiated int[] (in which all values are 0).  If I randomly press the buttons on the screen, the application will ANR after 10-30seconds.

I don't think the ANR is dependent on the width and height values of the Bitmap being rendered, or the dimensions of the Bitmap that is used as the parameter in the Canvas' constructor.  However, it is dependent on the canvas.scale(.36f, .36f) that occurs prior to the bitmap rendering.  I'm not sure if values other than ".36" cause the ANR, but the ANR does not occur if no scaling happens prior to the drawBitmap call.  Also, the ANR does not occur unless the Canvas object is created with a Bitmap as its parameter.

So, my guess is that this is somehow related to the Samsung Note's native implementation of Canvas.drawBitmap.  Any ideas what would cause the GUI thread to be blocked and how it can be prevented?

http://pastebin.com/hummn87H

    public class TempActivity extends Activity implements android.view.View.OnClickListener
    {
    LinearLayout contentView;
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            
            Log.e("", ""+1);
            
            contentView = new LinearLayout(this);
            contentView.setOrientation(LinearLayout.VERTICAL);
            
            //add a few rows of image buttons
            contentView.addView(initRow());
            contentView.addView(initRow());
            contentView.addView(initRow());
            contentView.addView(initRow());
            contentView.addView(initRow());
            contentView.addView(initRow());
            
            setContentView(contentView);
            
            RenderThread task1 = new RenderThread();
            task1.start();
        }
        
        public class RenderThread extends Thread 
        {
            public void run() 
            {
            Paint paint = new Paint();
            Bitmap bitmap = Bitmap.createBitmap(500, 500, Config.ARGB_8888);
           
            int width = 800;
            int height = 1000;
           
            int[] pixels = new int[width];
           
            while (1!= 0)
    {
    Canvas canvas = new Canvas(bitmap);
    canvas.scale(.36f, .36f);
    for(int i = 0; i < height; i++)
       {
    canvas.drawBitmap(pixels, 0, width, 0, i, width, 1, false, paint);
       }
    }
            }
        }
        
        private View initRow()
        {
        LinearLayout row = new LinearLayout(this);
             row.setOrientation(LinearLayout.HORIZONTAL);
             ImageButton button = new ImageButton(this);
             button.setImageResource(R.drawable.icon);
             button.setOnClickListener(this);
             row.addView(button);
             button = new ImageButton(this);
             button.setImageResource(R.drawable.icon);
             button.setOnClickListener(this);
             row.addView(button);
             button = new ImageButton(this);
             button.setImageResource(R.drawable.icon);
             button.setOnClickListener(this);
             row.addView(button);
             button = new ImageButton(this);
             button.setImageResource(R.drawable.icon);
             button.setOnClickListener(this);
             row.addView(button);
             button = new ImageButton(this);
             button.setImageResource(R.drawable.icon);
             button.setOnClickListener(this);
             row.addView(button);
             button = new ImageButton(this);
             button.setImageResource(R.drawable.icon);
             button.setOnClickListener(this);
             row.addView(button);
             
             return row;
        }
    
    @Override
    public void onClick(View v) 
    {
    contentView.postInvalidate();
    }    
    }

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

No comments:

Post a Comment