Move SurfaceView offscreen if the app stops drawing it

Bug: 29360411
Change-Id: Iefb9d7a9dafb34a2b4f79130a2a8b5a7cf7de906
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 5a3300a..f8797bf 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -474,7 +474,7 @@
 }
 #endif
 
-void RenderNode::syncDisplayList(TreeObserver* observer) {
+void RenderNode::syncDisplayList(TreeInfo* info) {
     // Make sure we inc first so that we don't fluctuate between 0 and 1,
     // which would thrash the layer cache
     if (mStagingDisplayList) {
@@ -482,7 +482,7 @@
             child->renderNode->incParentRefCount();
         }
     }
-    deleteDisplayList(observer);
+    deleteDisplayList(info ? info->observer : nullptr, info);
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
@@ -501,15 +501,15 @@
         // Damage with the old display list first then the new one to catch any
         // changes in isRenderable or, in the future, bounds
         damageSelf(info);
-        syncDisplayList(info.observer);
+        syncDisplayList(&info);
         damageSelf(info);
     }
 }
 
-void RenderNode::deleteDisplayList(TreeObserver* observer) {
+void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
     if (mDisplayList) {
         for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->decParentRefCount(observer);
+            child->renderNode->decParentRefCount(observer, info);
         }
     }
     delete mDisplayList;
@@ -541,35 +541,38 @@
     }
 }
 
-void RenderNode::destroyHardwareResources(TreeObserver* observer) {
+void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) {
     if (mLayer) {
         destroyLayer(mLayer);
         mLayer = nullptr;
     }
     if (mDisplayList) {
         for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->destroyHardwareResources(observer);
+            child->renderNode->destroyHardwareResources(observer, info);
         }
         if (mNeedsDisplayListSync) {
             // Next prepare tree we are going to push a new display list, so we can
             // drop our current one now
-            deleteDisplayList(observer);
+            deleteDisplayList(observer, info);
         }
     }
 }
 
-void RenderNode::decParentRefCount(TreeObserver* observer) {
+void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) {
     LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!");
     mParentCount--;
     if (!mParentCount) {
         if (observer) {
             observer->onMaybeRemovedFromTree(this);
         }
+        if (CC_UNLIKELY(mPositionListener.get())) {
+            mPositionListener->onPositionLost(*this, info);
+        }
         // If a child of ours is being attached to our parent then this will incorrectly
         // destroy its hardware resources. However, this situation is highly unlikely
         // and the failure is "just" that the layer is re-created, so this should
         // be safe enough
-        destroyHardwareResources(observer);
+        destroyHardwareResources(observer, info);
     }
 }
 
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index acdc3d8..f80be5e 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -196,7 +196,7 @@
     }
 
     ANDROID_API virtual void prepareTree(TreeInfo& info);
-    void destroyHardwareResources(TreeObserver* observer);
+    void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr);
 
     // UI thread only!
     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
@@ -228,10 +228,19 @@
     OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
 #endif
 
+    // Note: The position callbacks are relying on the listener using
+    // the frameNumber to appropriately batch/synchronize these transactions.
+    // There is no other filtering/batching to ensure that only the "final"
+    // state called once per frame.
     class ANDROID_API PositionListener {
     public:
         virtual ~PositionListener() {}
+        // Called when the RenderNode's position changes
         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
+        // Called when the RenderNode no longer has a position. As in, it's
+        // no longer being drawn.
+        // Note, tree info might be null
+        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
     };
 
     // Note this is not thread safe, this needs to be called
@@ -306,7 +315,7 @@
 
 
     void syncProperties();
-    void syncDisplayList(TreeObserver* observer);
+    void syncDisplayList(TreeInfo* info);
 
     void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
     void pushStagingPropertiesChanges(TreeInfo& info);
@@ -317,11 +326,11 @@
 #endif
     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
     void pushLayerUpdate(TreeInfo& info);
-    void deleteDisplayList(TreeObserver* observer);
+    void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
     void damageSelf(TreeInfo& info);
 
     void incParentRefCount() { mParentCount++; }
-    void decParentRefCount(TreeObserver* observer);
+    void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);
 
     String8 mName;
     sp<VirtualLightRefBase> mUserContext;