android: More robust fix for screen locking in landscape (thanks, Sylvain!).

Fixes Bugzilla #3562.

From Sylvain:

"With an android landscape application, if you quickly lock, then unlock your
device, you can see sometimes a quick glitch: screen badly draws in portrait,
then it correctly displays in landscape.

Not talking of a smooth rotation, it's a drawing glitch. And you need to have
a plain lock screen, with no model nor passphrase.


I think it happens because the call to "nativeResume()" occurs sometimes too
early.

It should be done once you have *all* those three things (in any sequence):
- onWindowsFocusChanged() set to true
- onResume() called
- a valid call to onSurfaceChanged()


Currently, this is not the case: you don't need to have onResume() called.
Just need to have isPaused, (eg onPaused()).
So "isPaused" should be renamed as "isResumedCalled".
But you also need some kind of isPaused state to make sure to don't call
nativePause() twice (and deadlocks...).
There are also redundant checks to "mHasFocus" and some creation of the
initialisation thread code from onSurfaceChanged() that could me moved.

So here's this patch:
- add some states, so we have cleaner transitions.
- make sure "onResume()" is called.
- some clean up
- it also goes faster in pause state (focus changed, onPause, without requiring isSurfaceReady which does seems to be needed).


Tested on a few devices and it removes the glitch.
But I haven't tested when the activity goes back to "init" state."
diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java
index a49184b..8fbbd78 100644
--- a/android-project/src/org/libsdl/app/SDLActivity.java
+++ b/android-project/src/org/libsdl/app/SDLActivity.java
@@ -36,8 +36,16 @@
 public class SDLActivity extends Activity {
     private static final String TAG = "SDL";
 
-    // Keep track of the paused state
-    public static boolean mIsPaused, mIsSurfaceReady, mHasFocus;
+    public static boolean mIsResumedCalled, mIsSurfaceReady, mHasFocus;
+
+    // Handle the state of the native layer
+    public enum NativeState {
+           INIT, RESUMED, PAUSED 
+    }
+
+    public static NativeState mNextNativeState;
+    public static NativeState mCurrentNativeState;
+
     public static boolean mExitCalledFromJava;
 
     /** If shared libraries (e.g. SDL or the native application) could not be loaded. */
@@ -110,9 +118,11 @@
         mAudioRecord = null;
         mExitCalledFromJava = false;
         mBrokenLibraries = false;
-        mIsPaused = false;
+        mIsResumedCalled = false;
         mIsSurfaceReady = false;
         mHasFocus = true;
+        mNextNativeState = NativeState.INIT;
+        mCurrentNativeState = NativeState.INIT;
     }
 
     // Setup
@@ -195,24 +205,28 @@
     protected void onPause() {
         Log.v(TAG, "onPause()");
         super.onPause();
+        mNextNativeState = NativeState.PAUSED;
+        mIsResumedCalled = false;
 
         if (SDLActivity.mBrokenLibraries) {
            return;
         }
 
-        SDLActivity.handlePause();
+        SDLActivity.handleNativeState();
     }
 
     @Override
     protected void onResume() {
         Log.v(TAG, "onResume()");
         super.onResume();
+        mNextNativeState = NativeState.RESUMED;
+        mIsResumedCalled = true;
 
         if (SDLActivity.mBrokenLibraries) {
            return;
         }
 
-        SDLActivity.handleResume();
+        SDLActivity.handleNativeState();
     }
 
 
@@ -227,8 +241,12 @@
 
         SDLActivity.mHasFocus = hasFocus;
         if (hasFocus) {
-            SDLActivity.handleResume();
+           mNextNativeState = NativeState.RESUMED;
+        } else {
+           mNextNativeState = NativeState.PAUSED;
         }
+        
+        SDLActivity.handleNativeState();
     }
 
     @Override
@@ -247,6 +265,9 @@
     protected void onDestroy() {
         Log.v(TAG, "onDestroy()");
 
+        mNextNativeState = NativeState.PAUSED;
+        SDLActivity.handleNativeState();
+
         if (SDLActivity.mBrokenLibraries) {
            super.onDestroy();
            // Reset everything in case the user re opens the app
@@ -295,28 +316,68 @@
         return super.dispatchKeyEvent(event);
     }
 
-    /** Called by onPause or surfaceDestroyed. Even if surfaceDestroyed
-     *  is the first to be called, mIsSurfaceReady should still be set
-     *  to 'true' during the call to onPause (in a usual scenario).
-     */
-    public static void handlePause() {
-        if (!SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady) {
-            SDLActivity.mIsPaused = true;
-            SDLActivity.nativePause();
-            mSurface.handlePause();
-        }
-    }
+    /* Transition to next state */
+    public static void handleNativeState() {
 
-    /** Called by onResume or surfaceCreated. An actual resume should be done only when the surface is ready.
-     * Note: Some Android variants may send multiple surfaceChanged events, so we don't need to resume
-     * every time we get one of those events, only if it comes after surfaceDestroyed
-     */
-    public static void handleResume() {
-        if (SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady && SDLActivity.mHasFocus) {
-            SDLActivity.mIsPaused = false;
-            SDLActivity.nativeResume();
-            mSurface.handleResume();
+        if (mNextNativeState == mCurrentNativeState) {
+            // Already in same state, discard.
+            return;
         }
+
+        // Try a transition to init state
+        if (mNextNativeState == NativeState.INIT) {
+
+            mCurrentNativeState = mNextNativeState;
+            return;
+        }
+
+        // Try a transition to paused state
+        if (mNextNativeState == NativeState.PAUSED) {
+            nativePause();
+            mSurface.handlePause();
+            mCurrentNativeState = mNextNativeState;
+            return;
+        }
+
+        // Try a transition to resumed state
+        if (mNextNativeState == NativeState.RESUMED) {
+
+           if (mIsSurfaceReady && mHasFocus && mIsResumedCalled) {
+
+              if (mSDLThread == null) {
+                  // This is the entry point to the C app.
+                  // Start up the C app thread and enable sensor input for the first time
+
+                  final Thread sdlThread = new Thread(new SDLMain(), "SDLThread");
+                  mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
+                  sdlThread.start();
+
+                  // Set up a listener thread to catch when the native thread ends
+                  mSDLThread = new Thread(new Runnable(){
+                      @Override
+                      public void run(){
+                          try {
+                              sdlThread.join();
+                          }
+                          catch(Exception e){}
+                          finally{
+                              // Native thread has finished
+                              if (! mExitCalledFromJava) {
+                                  handleNativeExit();
+                              }
+                          }
+                      }
+                  }, "SDLThreadListener");
+                  mSDLThread.start();
+              }
+
+
+              nativeResume();
+              mSurface.handleResume();
+              mCurrentNativeState = mNextNativeState;
+          }
+          return;
+       }
     }
 
     /* The native thread has finished */
@@ -1099,8 +1160,11 @@
     @Override
     public void surfaceDestroyed(SurfaceHolder holder) {
         Log.v("SDL", "surfaceDestroyed()");
-        // Call this *before* setting mIsSurfaceReady to 'false'
-        SDLActivity.handlePause();
+
+        // Transition to pause, if needed
+        SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
+        SDLActivity.handleNativeState();
+
         SDLActivity.mIsSurfaceReady = false;
         SDLActivity.onNativeSurfaceDestroyed();
     }
@@ -1193,45 +1257,17 @@
 
         if (skip) {
            Log.v("SDL", "Skip .. Surface is not ready.");
+           SDLActivity.mIsSurfaceReady = false;
            return;
         }
-
-
-        // Set mIsSurfaceReady to 'true' *before* making a call to handleResume
+        
+        /* Surface is ready */
         SDLActivity.mIsSurfaceReady = true;
+
+        /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
         SDLActivity.onNativeSurfaceChanged();
 
-
-        if (SDLActivity.mSDLThread == null) {
-            // This is the entry point to the C app.
-            // Start up the C app thread and enable sensor input for the first time
-
-            final Thread sdlThread = new Thread(new SDLMain(), "SDLThread");
-            enableSensor(Sensor.TYPE_ACCELEROMETER, true);
-            sdlThread.start();
-
-            // Set up a listener thread to catch when the native thread ends
-            SDLActivity.mSDLThread = new Thread(new Runnable(){
-                @Override
-                public void run(){
-                    try {
-                        sdlThread.join();
-                    }
-                    catch(Exception e){}
-                    finally{
-                        // Native thread has finished
-                        if (! SDLActivity.mExitCalledFromJava) {
-                            SDLActivity.handleNativeExit();
-                        }
-                    }
-                }
-            }, "SDLThreadListener");
-            SDLActivity.mSDLThread.start();
-        }
-
-        if (SDLActivity.mHasFocus && !SDLActivity.mIsPaused) {
-            SDLActivity.handleResume();
-        }
+        SDLActivity.handleNativeState();
     }
 
     // Key events