title: Android Game - how correctly handle onPause and onResume if game runs in GLSurfaceView's video thread
body: <p>I work on c++ game which runs in GLSurfaceView's video thread (game's loop is loop of GLSurfaceView, because it runs in continuos mode). I have problems how to correctly handle Activity.onPause/onResume together with nativePause of my game. In nativePause i release opengl resources and various big data. I don't have nativeResume, because this is handled by Android when I call GLSurfaceView.onResume() which calls again methods onSurfaceCreated/onSurfaceChanged , in which I allocate again my resources. </p>
  
  <p>Here is how I do it now :</p>
  
  <p>OnPause</p>
  
  <p>Activity in java handles onPause and runs custom nativePause method of glSurfaceView:</p>
  
  <pre><code>@Override
  protected void onPause() {
      super.onPause();
  
      glSurfaceView.nativePause();
  }
  </code></pre>
  
  <p>nativePause sends asynchronous request to game's video loop. In video loop is handled and various resources are released. Next, is send another message to main thread with information that nativePause is finished and I do GLSurfaceView.onPause(), this stops video thread.</p>
  
  <p>onResume</p>
  
  <p>this method has simple implementation, it only starts surfaceview's video thread with onResume()</p>
  
  <pre><code>@Override
  protected void onResume() {
      super.onResume();
  
      glSurfaceView.onResume();
  }
  </code></pre>
  
  <p>But problem is, onPause does asynchronous calls to video thread and back to main thread. Activity.onResume is often called sooner before whole pausing mechanism is finished and then it crashes or hangs. How should I handle onPause/onResume correctly if game runs in video thread?</p>
  
  <p>EDIT :</p>
  
  <p>Java side :</p>
  
  <pre><code>public class RendererWrapper implements Renderer {
      public native void onSurfaceCreated();
      public native void onSurfaceChanged(int width, int height);
      public native void onDrawFrame();
  ....
      @Override
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
          onSurfaceCreated();
      }
  
      @Override
      public void onSurfaceChanged(GL10 gl, int width, int height) {
          onSurfaceChanged(width, height);
      }
  
      @Override
      public void onDrawFrame(GL10 gl) {
          onDrawFrame();
      }
  ....
  }
  
  public class VideoSurface extends GLSurfaceView {
      public VideoSurface(Context context) {
          super(context);
  
          this.setEGLContextClientVersion(2);
          this.renderer = new RendererWrapper();
          this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
          this.setRenderer(renderer);
          this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
      }
  
      public native void nativePause();
  }
  </code></pre>
  
  <p>Native onDrawFrame() in RendererWrapper is main game loop.</p>
  
  <p>C++ side</p>
  
  <pre><code>void nativePause() {
      InputEvent *event = inputQueue.getWriteEvent();
      event-&gt;type = InputEvent::PAUSE;
  
      inputQueue.incWriteIndex();
  }
  
  void onDrawFrame() {
      if (isPaused) {
          return;
      }
  
      InputEvent *event = inputQueue.getReadEvent();
      if (event) {
          inputQueue.incReadIndex();
  
          ....
          if (event-&gt;type == InputEvent::PAUSE) {
              release();
              return;
          }
      }
  
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
  
      game-&gt;draw();
  }
  </code></pre>
  
  <p>EDIT2 :</p>
  
  <pre><code>class EventQueue {
  public:
      static const int size = 256;
      volatile int readIndex;
      volatile int writeIndex;
      InputEvent *events;
  
      EventQueue() {
          readIndex = 0;
          writeIndex = 0;
          events = new InputEvent[size];
      }
  
      InputEvent* getReadEvent() {
          if (writeIndex == readIndex) {
              return 0; // queue empty
          }
          return events + readIndex;
      }
  
      InputEvent* getWriteEvent() {
          if (((writeIndex + 2) &amp; (size - 1)) == readIndex) {
              return 0; // queue full
          }
          return events + writeIndex;
      }
  
      void incReadIndex() {
          readIndex = (readIndex + 1) &amp; (size - 1);
      }
  
      void incWriteIndex() {
          writeIndex = (writeIndex + 1) &amp; (size - 1);
      }
  };
  </code></pre>