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);