Fix some edge cases

Bug: 27709981

This desperately needs a refactor, but to keep
the current (really needed & nice) behavior of
dispatching after sync finishes would be difficult
to handle cleanly without lots of ripping so... #yolo

Change-Id: I831a06c6ae7412a062720d68ecbe3085190f0258
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 63fa788..ab66b2a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -76,15 +76,15 @@
 }
 
 CanvasContext::~CanvasContext() {
-    destroy();
+    destroy(nullptr);
     mRenderThread.renderState().unregisterCanvasContext(this);
 }
 
-void CanvasContext::destroy() {
+void CanvasContext::destroy(TreeObserver* observer) {
     stopDrawing();
     setSurface(nullptr);
-    freePrefetechedLayers();
-    destroyHardwareResources();
+    freePrefetchedLayers(observer);
+    destroyHardwareResources(observer);
     mAnimationContext->destroy();
 #if !HWUI_NEW_OPS
     if (mCanvas) {
@@ -222,7 +222,7 @@
     mAnimationContext->runRemainingAnimations(info);
     GL_CHECKPOINT(MODERATE);
 
-    freePrefetechedLayers();
+    freePrefetchedLayers(info.observer);
     GL_CHECKPOINT(MODERATE);
 
     if (CC_UNLIKELY(!mNativeSurface.get())) {
@@ -569,25 +569,24 @@
 }
 
 void CanvasContext::markLayerInUse(RenderNode* node) {
-    if (mPrefetechedLayers.erase(node)) {
+    if (mPrefetchedLayers.erase(node)) {
         node->decStrong(nullptr);
     }
 }
 
-static void destroyPrefetechedNode(RenderNode* node) {
-    ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName());
-    node->destroyHardwareResources(nullptr);
-    node->decStrong(nullptr);
-}
-
-void CanvasContext::freePrefetechedLayers() {
-    if (mPrefetechedLayers.size()) {
-        std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode);
-        mPrefetechedLayers.clear();
+void CanvasContext::freePrefetchedLayers(TreeObserver* observer) {
+    if (mPrefetchedLayers.size()) {
+        for (auto& node : mPrefetchedLayers) {
+            ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
+                    node->getName());
+            node->destroyHardwareResources(observer);
+            node->decStrong(observer);
+        }
+        mPrefetchedLayers.clear();
     }
 }
 
-void CanvasContext::buildLayer(RenderNode* node) {
+void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
     ATRACE_CALL();
     if (!mEglManager.hasEglContext()) return;
 #if !HWUI_NEW_OPS
@@ -599,6 +598,7 @@
 
     TreeInfo info(TreeInfo::MODE_FULL, *this);
     info.damageAccumulator = &mDamageAccumulator;
+    info.observer = observer;
 #if HWUI_NEW_OPS
     info.layerUpdateQueue = &mLayerUpdateQueue;
 #else
@@ -628,7 +628,7 @@
 #endif
 
     node->incStrong(nullptr);
-    mPrefetechedLayers.insert(node);
+    mPrefetchedLayers.insert(node);
 }
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
@@ -636,12 +636,12 @@
     return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
 }
 
-void CanvasContext::destroyHardwareResources() {
+void CanvasContext::destroyHardwareResources(TreeObserver* observer) {
     stopDrawing();
     if (mEglManager.hasEglContext()) {
-        freePrefetechedLayers();
+        freePrefetchedLayers(observer);
         for (const sp<RenderNode>& node : mRenderNodes) {
-            node->destroyHardwareResources(nullptr);
+            node->destroyHardwareResources(observer);
         }
         Caches& caches = Caches::getInstance();
         // Make sure to release all the textures we were owning as there won't
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6d0889e..9350114 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -92,17 +92,17 @@
     void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
             int64_t syncQueued, RenderNode* target);
     void draw();
-    void destroy();
+    void destroy(TreeObserver* observer);
 
     // IFrameCallback, Choreographer-driven frame callback entry point
     virtual void doFrame() override;
     void prepareAndDraw(RenderNode* node);
 
-    void buildLayer(RenderNode* node);
+    void buildLayer(RenderNode* node, TreeObserver* observer);
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
     void markLayerInUse(RenderNode* node);
 
-    void destroyHardwareResources();
+    void destroyHardwareResources(TreeObserver* observer);
     static void trimMemory(RenderThread& thread, int level);
 
     static void invokeFunctor(RenderThread& thread, Functor* functor);
@@ -174,7 +174,7 @@
     void setSurface(Surface* window);
     void requireSurface();
 
-    void freePrefetechedLayers();
+    void freePrefetchedLayers(TreeObserver* observer);
 
     void waitOnFences();
 
@@ -218,7 +218,7 @@
     FrameInfoVisualizer mProfiler;
     std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter;
 
-    std::set<RenderNode*> mPrefetechedLayers;
+    std::set<RenderNode*> mPrefetchedLayers;
 
     // Stores the bounds of the main content.
     Rect mContentDrawBounds;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index e8b9725..651aaa2 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -65,11 +65,12 @@
     }
 }
 
-int DrawFrameTask::drawFrame() {
+int DrawFrameTask::drawFrame(TreeObserver* observer) {
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
     mSyncResult = kSync_OK;
     mSyncQueued = systemTime(CLOCK_MONOTONIC);
+    mObserver = observer;
     postAndWait();
 
     return mSyncResult;
@@ -88,6 +89,7 @@
     bool canDrawThisFrame;
     {
         TreeInfo info(TreeInfo::MODE_FULL, *mContext);
+        info.observer = mObserver;
         canUnblockUiThread = syncFrameState(info);
         canDrawThisFrame = info.out.canDrawThisFrame;
     }
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index cae251a9..9bba065 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -62,7 +62,7 @@
     void pushLayerUpdate(DeferredLayerUpdater* layer);
     void removeLayerUpdate(DeferredLayerUpdater* layer);
 
-    int drawFrame();
+    int drawFrame(TreeObserver* observer);
 
     int64_t* frameInfo() { return mFrameInfo; }
 
@@ -87,6 +87,7 @@
 
     int mSyncResult;
     int64_t mSyncQueued;
+    TreeObserver* mObserver;
 
     int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
 };
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 16dd108..2e99d0b 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -222,18 +222,19 @@
     return mDrawFrameTask.frameInfo();
 }
 
-int RenderProxy::syncAndDrawFrame() {
-    return mDrawFrameTask.drawFrame();
+int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
+    return mDrawFrameTask.drawFrame(observer);
 }
 
-CREATE_BRIDGE1(destroy, CanvasContext* context) {
-    args->context->destroy();
+CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
+    args->context->destroy(args->observer);
     return nullptr;
 }
 
-void RenderProxy::destroy() {
+void RenderProxy::destroy(TreeObserver* observer) {
     SETUP_TASK(destroy);
     args->context = mContext;
+    args->observer = observer;
     // destroyCanvasAndSurface() needs a fence as when it returns the
     // underlying BufferQueue is going to be released from under
     // the render thread.
@@ -287,15 +288,16 @@
     return layer;
 }
 
-CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
-    args->context->buildLayer(args->node);
+CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
+    args->context->buildLayer(args->node, args->observer);
     return nullptr;
 }
 
-void RenderProxy::buildLayer(RenderNode* node) {
+void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
     SETUP_TASK(buildLayer);
     args->context = mContext;
     args->node = node;
+    args->observer = observer;
     postAndWait(task);
 }
 
@@ -332,15 +334,16 @@
     postAndWait(task);
 }
 
-CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
-    args->context->destroyHardwareResources();
+CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
+    args->context->destroyHardwareResources(args->observer);
     return nullptr;
 }
 
-void RenderProxy::destroyHardwareResources() {
+void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
     SETUP_TASK(destroyHardwareResources);
     args->context = mContext;
-    post(task);
+    args->observer = observer;
+    postAndWait(task);
 }
 
 CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 8d65a82..97194fe 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -42,6 +42,7 @@
 class DisplayList;
 class Layer;
 class Rect;
+class TreeObserver;
 
 namespace renderthread {
 
@@ -75,21 +76,21 @@
     ANDROID_API void setLightCenter(const Vector3& lightCenter);
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API int64_t* frameInfo();
-    ANDROID_API int syncAndDrawFrame();
-    ANDROID_API void destroy();
+    ANDROID_API int syncAndDrawFrame(TreeObserver* observer);
+    ANDROID_API void destroy(TreeObserver* observer);
 
     ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
 
     ANDROID_API void runWithGlContext(RenderTask* task);
 
     ANDROID_API DeferredLayerUpdater* createTextureLayer();
-    ANDROID_API void buildLayer(RenderNode* node);
+    ANDROID_API void buildLayer(RenderNode* node, TreeObserver* observer);
     ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
     ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
 
-    ANDROID_API void destroyHardwareResources();
+    ANDROID_API void destroyHardwareResources(TreeObserver* observer);
     ANDROID_API static void trimMemory(int level);
     ANDROID_API static void overrideProperty(const char* name, const char* value);