Fix ReliableSurface to be more reliable

Handle TIMED_OUT better by rescheduling (TODO: give up after N
attempts?)

Fix SYNC_SURFACE_LOST_REWARD_IF_FOUND path to actually go fetch
a new surface.

Bug: 137509524
Test: Injected errors randomly, verified nothing got permanently dead.
Change-Id: Id30f8ad1dd7196041ee84c16c8cf5c814002a6ce
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index d97c5ed..d19351b 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -450,20 +450,38 @@
     waitOnFences();
 
     bool requireSwap = false;
+    int error = OK;
     bool didSwap =
             mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
 
     mIsDirty = false;
 
     if (requireSwap) {
-        if (!didSwap) {  // some error happened
+        bool didDraw = true;
+        // Handle any swapchain errors
+        error = mNativeSurface->getAndClearError();
+        if (error == TIMED_OUT) {
+            // Try again
+            mRenderThread.postFrameCallback(this);
+            // But since this frame didn't happen, we need to mark full damage in the swap
+            // history
+            didDraw = false;
+
+        } else if (error != OK || !didSwap) {
+            // Unknown error, abandon the surface
             setSurface(nullptr);
+            didDraw = false;
         }
+
         SwapHistory& swap = mSwapHistory.next();
-        swap.damage = windowDirty;
+        if (didDraw) {
+            swap.damage = windowDirty;
+        } else {
+            swap.damage = SkRect::MakeWH(INT_MAX, INT_MAX);
+        }
         swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC);
         swap.vsyncTime = mRenderThread.timeLord().latestVsync();
-        if (mNativeSurface.get()) {
+        if (didDraw) {
             int durationUs;
             nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime();
             if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) {