Allow the window to be recreated in the middle of a test
authorLloyd Pique <lpique@google.com>
Wed, 25 Apr 2018 02:08:39 +0000 (19:08 -0700)
committerLloyd Pique <lpique@google.com>
Wed, 25 Apr 2018 19:19:08 +0000 (12:19 -0700)
On ARC++ devices, some of the dEQP CTS tests were occasionally failing on
devices running in tablet mode, due to the timing of a WM relayout that
happens shortly after the orientation change is realized.

We traced it back to the dEQP test harness always expecting to see a
call from the system to onNativeWindowResized() after a call to
oNNativeWindowCreated(). It happened that the relayout on ARC++ devices
was not causing a size change, so this message was never received.

The result was that the test paused itself, and never completed. The
watchdog thread that the test harness creates ended up killing and
failing the test.

This patch adjusts the logic so that the activity only waits to process
the window creation for the very first call to onNativeWindowResized(),
as when the activity is first created that call is indeed made (but note
not really guaranteed). A subsequent call to onNativeWindowCreated()
will unpause the test (setting the READY state), as well as finish
processing the window creation.

Bug: 74371892
Test: dEQP-GLES3.functional.prerequisite#clear_color
Change-Id: I3c429aea272cbfee3f150a32c12233c9f38a7936

framework/platform/android/tcuAndroidRenderActivity.cpp
framework/platform/android/tcuAndroidRenderActivity.hpp

index ddbf40e..0c3bd19 100644 (file)
@@ -78,6 +78,7 @@ RenderThread::RenderThread (NativeActivity& activity)
        , m_window                      (DE_NULL)
        , m_paused                      (false)
        , m_finish                      (false)
+       , m_receivedFirstResize(false)
 {
 }
 
@@ -143,7 +144,29 @@ void RenderThread::processMessage (const Message& message)
                        if (m_windowState != WINDOWSTATE_NOT_CREATED && m_windowState != WINDOWSTATE_DESTROYED)
                                throw InternalError("Got unexpected onNativeWindowCreated() event from system");
 
-                       m_windowState   = WINDOWSTATE_NOT_INITIALIZED;
+                       // The documented behavior for the callbacks is that the native activity
+                       // will get a call to onNativeWindowCreated(), at which point it should have
+                       // a surface to render to, and can then start immediately.
+                       //
+                       // The actual creation process has the framework making calls to both
+                       // onNativeWindowCreated() and then onNativeWindowResized(). The test
+                       // waits for that first resize before it considers the window ready for
+                       // rendering.
+                       //
+                       // However subsequent events in the framework may cause the window to be
+                       // recreated at a new position without a size change, which sends on
+                       // onNativeWindowDestroyed(), and then on onNativeWindowCreated() without
+                       // a follow-up onNativeWindowResized(). If this happens, the test will
+                       // stop rendering as it is no longer in the ready state, and a watchdog
+                       // thread will eventually kill the test, causing it to fail. We therefore
+                       // set the window state back to READY and process the window creation here
+                       // if we have already observed that first resize call.
+                       if (!m_receivedFirstResize) {
+                               m_windowState   = WINDOWSTATE_NOT_INITIALIZED;
+                       } else {
+                               m_windowState   = WINDOWSTATE_READY;
+                               onWindowCreated(message.payload.window);
+                       }
                        m_window                = message.payload.window;
                        break;
 
@@ -151,6 +174,10 @@ void RenderThread::processMessage (const Message& message)
                        if (m_window != message.payload.window)
                                throw InternalError("Got onNativeWindowResized() event targeting different window");
 
+                       // Record that we've the first resize event, in case the window is
+                       // recreated later without a resize.
+                       m_receivedFirstResize = true;
+
                        if (m_windowState == WINDOWSTATE_NOT_INITIALIZED)
                        {
                                // Got first resize event, window is ready for use.
index e2e7331..9cad495 100644 (file)
@@ -158,6 +158,7 @@ private:
        ANativeWindow*                  m_window;
        bool                                    m_paused;                                       //!< Is rendering paused?
        bool                                    m_finish;                                       //!< Has thread received FINISH message?
+       bool                                    m_receivedFirstResize;                          //!< Has the first onWindowResized been processed?
 };
 
 class RenderActivity : public NativeActivity