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)) {
diff --git a/libs/hwui/renderthread/ReliableSurface.cpp b/libs/hwui/renderthread/ReliableSurface.cpp
index ad1fc49..a44b804 100644
--- a/libs/hwui/renderthread/ReliableSurface.cpp
+++ b/libs/hwui/renderthread/ReliableSurface.cpp
@@ -87,21 +87,21 @@
 }
 
 int ReliableSurface::reserveNext() {
+    if constexpr (DISABLE_BUFFER_PREFETCH) {
+        return OK;
+    }
     {
         std::lock_guard _lock{mMutex};
         if (mReservedBuffer) {
             ALOGW("reserveNext called but there was already a buffer reserved?");
             return OK;
         }
-        if (mInErrorState) {
+        if (mBufferQueueState != OK) {
             return UNKNOWN_ERROR;
         }
         if (mHasDequeuedBuffer) {
             return OK;
         }
-        if constexpr (DISABLE_BUFFER_PREFETCH) {
-            return OK;
-        }
     }
 
     // TODO: Update this to better handle when requested dimensions have changed
@@ -165,10 +165,11 @@
         }
     }
 
+
     int result = callProtected(mSurface, dequeueBuffer, buffer, fenceFd);
     if (result != OK) {
         ALOGW("dequeueBuffer failed, error = %d; switching to fallback", result);
-        *buffer = acquireFallbackBuffer();
+        *buffer = acquireFallbackBuffer(result);
         *fenceFd = -1;
         return *buffer ? OK : INVALID_OPERATION;
     } else {
@@ -201,9 +202,9 @@
     return windowBuffer == scratchBuffer;
 }
 
-ANativeWindowBuffer* ReliableSurface::acquireFallbackBuffer() {
+ANativeWindowBuffer* ReliableSurface::acquireFallbackBuffer(int error) {
     std::lock_guard _lock{mMutex};
-    mInErrorState = true;
+    mBufferQueueState = error;
 
     if (mScratchBuffer) {
         return AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
diff --git a/libs/hwui/renderthread/ReliableSurface.h b/libs/hwui/renderthread/ReliableSurface.h
index 0bfc72e..41fc35e 100644
--- a/libs/hwui/renderthread/ReliableSurface.h
+++ b/libs/hwui/renderthread/ReliableSurface.h
@@ -43,6 +43,12 @@
 
     uint64_t getNextFrameNumber() const { return mSurface->getNextFrameNumber(); }
 
+    int getAndClearError() {
+        int ret = mBufferQueueState;
+        mBufferQueueState = OK;
+        return ret;
+    }
+
 private:
     const sp<Surface> mSurface;
 
@@ -55,10 +61,10 @@
     ANativeWindowBuffer* mReservedBuffer = nullptr;
     base::unique_fd mReservedFenceFd;
     bool mHasDequeuedBuffer = false;
-    bool mInErrorState = false;
+    int mBufferQueueState = OK;
 
     bool isFallbackBuffer(const ANativeWindowBuffer* windowBuffer) const;
-    ANativeWindowBuffer* acquireFallbackBuffer();
+    ANativeWindowBuffer* acquireFallbackBuffer(int error);
     void clearReservedBuffer();
 
     void perform(int operation, va_list args);