title: Android IllegalArgumentException lockCanvas()
body: <p>I've been struggling with this exception and I've looked around but there's nothing to help me.</p>
  
  <p>Here's the code</p>
  
  <pre><code>package com.example.surfacetest;
  
  import android.app.Activity;
  import android.content.Context;
  import android.graphics.BitmapFactory;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.MotionEvent;
  import android.view.Surface.OutOfResourcesException;
  import android.view.SurfaceHolder;
  import android.view.SurfaceView;
  
  public class BoardSurfaceActivity extends Activity {
      /** Called when the activity is first created. */
  
      private static final String TAG = BoardSurfaceActivity.class.getSimpleName();
      private BoardSurface bS;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          bS = new BoardSurface(this);
          setContentView(bS);
          Log.d(TAG, "View added");
      }
  
      @Override
      protected void onDestroy() {
          Log.d(TAG, "Destroying...");
          super.onDestroy();
      }
  
      @Override
      protected void onStop() {
          Log.d(TAG, "Stopping...");
          super.onStop();
      }
  
      @Override
      protected void onRestart() {
          // TODO Auto-generated method stub
          super.onRestart();
      }
  
      @Override
      protected void onPause() {
          Log.d(TAG, "Pausing...");
          super.onPause();
      }
  
      @Override
      protected void onResume() {
          Log.d(TAG, "Resuming...");
          super.onResume();
  
      }
  
      public class BoardSurface extends SurfaceView implements SurfaceHolder.Callback, Runnable {
          final String TAG = BoardSurface.class.getSimpleName();
          private Stuff stuff;
          Thread t = null;
          SurfaceHolder holder;
          boolean isItOk = false;
  
          public BoardSurface(Context context) {
              super(context);
              holder = getHolder();
              getHolder().addCallback(this);
              stuff = new Stuff(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher), 50, 50);
              t = new Thread(this);
              setFocusable(true);
          }
  
          @Override
          public void surfaceCreated(SurfaceHolder holder) {
              Log.d(TAG, "Surface created");
              resume();
          }
  
          @Override
          public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  
          }
  
          @Override
          public void surfaceDestroyed(SurfaceHolder holder) {
              Log.d(TAG, "Surface Destroyed");
              pause();
          }
  
          @Override
          public boolean onTouchEvent(MotionEvent event) {
              if (event.getAction() == MotionEvent.ACTION_DOWN) {
                  // delegating event handling to the droid
                  stuff.handleActionDown((int) event.getX(), (int) event.getY());
  
                  // check if in the lower part of the screen we exit
                  if (event.getY() &gt; getHeight() - 50) {
                      ((Activity) getContext()).finish();
                  } else {
                      Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
                  }
              }
              if (event.getAction() == MotionEvent.ACTION_MOVE) {
                  // the gestures
                  if (stuff.isTouched()) {
                      // the droid was picked up and is being dragged
                      stuff.setX((int) event.getX());
                      stuff.setY((int) event.getY());
                  }
              }
              if (event.getAction() == MotionEvent.ACTION_UP) {
                  // touch was released
                  if (stuff.isTouched()) {
                      stuff.setTouched(false);
                  }
              }
              return true;
          }
  
          public void draw(Canvas canvas) {
              canvas.drawColor(Color.BLUE);
              stuff.draw(canvas);
          }
  
          @Override
          public void run() {
              while (isItOk) {
                  holder = getHolder();
                  if (holder.getSurface().isValid()) {
  
                      Canvas c = null;
                      try {
                          // make sure holder is updated
                          c = holder.lockCanvas(null);
                          if (c != null) {
                              synchronized (holder) {
                                  draw(c);
                              }
                          }
                      } catch (IllegalArgumentException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      } finally {
                          if (c != null) {
                              holder.unlockCanvasAndPost(c);
                          }
                      }
                  }
              }
          }
  
          public void pause() {
              isItOk = false;
              while (true) {
                  try {
                      t.join();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  break;
              }
              t = null;
          }
  
          public void resume() {
              if (t.getState() == Thread.State.TERMINATED) {
                  t = new Thread(this);
                  isItOk = true;
                  t.start();
              } else {
                  isItOk = true;
                  t.start();
              }
  
          }
      }
  }
  </code></pre>
  
  <p>What is super strange is that I have this trace :</p>
  
  <pre><code>10-22 08:54:41.153: D/BoardSurface(17298): Surface created
  10-22 08:54:41.394: E/memalloc(17298): /dev/pmem: Failed to map buffer size:24641536 offset:23699456 fd:56 Error: Invalid argument
  10-22 08:54:41.394: E/gralloc(17298): Could not mmap handle 0x89e2b8, fd=56 (Invalid argument)
  10-22 08:54:41.394: E/gralloc(17298): gralloc_register_buffer: gralloc_map failed
  10-22 08:54:41.394: W/GraphicBufferMapper(17298): registerBuffer(0x89e2b8) failed -22 (Invalid argument)
  10-22 08:54:41.394: E/GraphicBuffer(17298): unflatten: registerBuffer failed: Invalid argument (-22)
  10-22 08:54:41.394: E/memalloc(17298): /dev/pmem: Failed to map buffer size:24641536 offset:23699456 fd:56 Error: Invalid argument
  10-22 08:54:41.394: E/gralloc(17298): Could not mmap handle 0x89e2b8, fd=56 (Invalid argument)
  10-22 08:54:41.394: E/libgenlock(17298): perform_lock_unlock_operation: GENLOCK_IOC_DREADLOCK failed (lockType0x1,err=Bad file number fd=56)
  10-22 08:54:41.394: E/gralloc(17298): gralloc_lock: genlock_lock_buffer (lockType=0x2) failed
  10-22 08:54:41.394: W/GraphicBufferMapper(17298): lock(...) failed -22 (Invalid argument)
  10-22 08:54:41.394: W/Surface(17298): failed locking buffer (handle = 0x89e2b8)
  10-22 08:54:41.424: E/SurfaceHolder(17298): Exception locking surface
  10-22 08:54:41.424: E/SurfaceHolder(17298): java.lang.IllegalArgumentException
  10-22 08:54:41.424: E/SurfaceHolder(17298):     at android.view.Surface.nativeLockCanvas(Native Method)
  10-22 08:54:41.424: E/SurfaceHolder(17298):     at android.view.Surface.lockCanvas(Surface.java:236)
  10-22 08:54:41.424: E/SurfaceHolder(17298):     at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:807)
  10-22 08:54:41.424: E/SurfaceHolder(17298):     at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:787)
  10-22 08:54:41.424: E/SurfaceHolder(17298):     at com.example.surfacetest.BoardSurfaceActivity$BoardSurface.run(BoardSurfaceActivity.java:137)
  10-22 08:54:41.424: E/SurfaceHolder(17298):     at java.lang.Thread.run(Thread.java:841)
  </code></pre>
  
  <p>in my running loop. </p>
  
  <p>But here's the tricky part ! When I press back (not HOME) then start the app from the menu again. It just simply works.</p>
  
  <p>So I really don't know what I'm missing.</p>
  
  <p>Additional info : I'm running on a HTC Sensation XE, CM 10.2 (Android 4.3.1)</p>
  
  <p>EDIT:</p>
  
  <p>The device is not the issue here. Tried with another HTC on stock ROM.</p>
  
  <p>EDIT 2 :</p>
  
  <p>Even though I check :</p>
  
  <pre><code>if (holder.getSurface().isValid())
  </code></pre>
  
  <p>Which is specifically saying that lockcanvas() will succeed if it is true, I get this exception</p>
  
  <pre><code>10-22 10:11:27.688: E/SurfaceHolder(22195): Exception locking surface
  10-22 10:11:27.688: E/SurfaceHolder(22195): java.lang.IllegalArgumentException
  10-22 10:11:27.688: E/SurfaceHolder(22195):     at android.view.Surface.nativeLockCanvas(Native Method)
  10-22 10:11:27.688: E/SurfaceHolder(22195):     at android.view.Surface.lockCanvas(Surface.java:236)
  10-22 10:11:27.688: E/SurfaceHolder(22195):     at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:807)
  10-22 10:11:27.688: E/SurfaceHolder(22195):     at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:787)
  10-22 10:11:27.688: E/SurfaceHolder(22195):     at com.example.surfacetest.BoardSurfaceActivity$BoardSurface.run(BoardSurfaceActivity.java:144)
  10-22 10:11:27.688: E/SurfaceHolder(22195):     at java.lang.Thread.run(Thread.java:841)
  </code></pre>
  
  <p>EDIT 3 : </p>
  
  <p>Works on Galaxy S4 Stock ROM and Emulator Intelx86 4.2.2</p>