Have an actual fallback if the surface is lost
Bug: 17516789
This will force a relayout/reinitialize pass if the Surface
is lost mid-render instead of crashing on the next frame
Change-Id: If08bfa16f740728fa7c05904fa11e26f07b81e2e
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 00a8884..5579c13 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -66,6 +66,8 @@
private static final int SYNC_OK = 0;
// Needs a ViewRoot invalidate
private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
+ // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
+ private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
private static final String[] VISUALIZERS = {
PROFILE_PROPERTY_VISUALIZE_BARS,
@@ -336,6 +338,12 @@
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
recordDuration, view.getResources().getDisplayMetrics().density);
+ if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
+ setEnabled(false);
+ // Invalidate since we failed to draw. This should fetch a Surface
+ // if it is still needed or do nothing if we are no longer drawing
+ attachInfo.mViewRootImpl.invalidate();
+ }
if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
attachInfo.mViewRootImpl.invalidate();
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b499dd0..6c3637d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -166,6 +166,11 @@
freePrefetechedLayers();
}
+ if (CC_UNLIKELY(!mNativeWindow.get())) {
+ info.out.canDrawThisFrame = false;
+ return;
+ }
+
int runningBehind = 0;
// TODO: This query is moderately expensive, investigate adding some sort
// of fast-path based off when we last called eglSwapBuffers() as well as
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e20564b..435244e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -68,6 +68,8 @@
bool initialize(ANativeWindow* window);
void updateSurface(ANativeWindow* window);
void pauseSurface(ANativeWindow* window);
+ bool hasSurface() { return mNativeWindow.get(); }
+
void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setOpaque(bool opaque);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index dd34e09..97b31a9 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -132,6 +132,12 @@
mLayers.clear();
mContext->prepareTree(info);
+ // This is after the prepareTree so that any pending operations
+ // (RenderNode tree state, prefetched layers, etc...) will be flushed.
+ if (CC_UNLIKELY(!mContext->hasSurface())) {
+ mSyncResult |= kSync_LostSurfaceRewardIfFound;
+ }
+
if (info.out.hasAnimations) {
if (info.out.requiresUiRedraw) {
mSyncResult |= kSync_UIRedrawRequired;
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 243cc5d..28f6cb2 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -42,6 +42,7 @@
enum SyncResult {
kSync_OK = 0,
kSync_UIRedrawRequired = 1 << 0,
+ kSync_LostSurfaceRewardIfFound = 1 << 1,
};
/*