Fixes for parentless layers

1. When a layer is removed, it needs to latch a buffer before the buffer
can be released.
2. If a layer is removed from current state, it needs to get re-added
back to current state when it gets reparented to a layer that is not
removed from current state
3. If a layer is added as a child to a layer that has been removed from
current state, the layer adding needs to succeed, but the layer needs to
be automatically set as removed from current state.

Bug: 111297488
Test: Test with updated ActivityView that has a SurfaceControl that has
no reference in SF tree
Change-Id: I8b723666964c61aaf7119b60ac256d19f85732b0
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index ade62bf..d314942 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -68,7 +68,7 @@
         ALOGE("Found stale hardware composer layers when destroying "
               "surface flinger layer %s",
               mName.string());
-        destroyAllHwcLayers();
+        destroyAllHwcLayersPlusChildren();
     }
 
     mTimeStats.onDestroy(getSequence());
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 038bc58..92a77b0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -123,7 +123,7 @@
 
     mFrameTracker.logAndResetStats(mName);
 
-    destroyAllHwcLayers();
+    destroyAllHwcLayersPlusChildren();
 
     mFlinger->onLayerDestroyed();
 }
@@ -175,6 +175,14 @@
     }
 }
 
+void Layer::addToCurrentState() {
+    mRemovedFromCurrentState = false;
+
+    for (const auto& child : mCurrentChildren) {
+        child->addToCurrentState();
+    }
+}
+
 // ---------------------------------------------------------------------------
 // set-up
 // ---------------------------------------------------------------------------
@@ -226,17 +234,21 @@
     return true;
 }
 
-void Layer::destroyAllHwcLayers() {
+void Layer::destroyHwcLayersForAllDisplays() {
     size_t numLayers = getBE().mHwcLayers.size();
     for (size_t i = 0; i < numLayers; ++i) {
         LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed");
         destroyHwcLayer(getBE().mHwcLayers.begin()->first);
     }
+}
+
+void Layer::destroyAllHwcLayersPlusChildren() {
+    destroyHwcLayersForAllDisplays();
     LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
                         "All hardware composer layers should have been destroyed");
 
     for (const sp<Layer>& child : mDrawingChildren) {
-        child->destroyAllHwcLayers();
+        child->destroyAllHwcLayersPlusChildren();
     }
 }
 
@@ -1587,6 +1599,10 @@
     }
     newParent->addChild(this);
 
+    if (!newParent->isRemovedFromCurrentState()) {
+        addToCurrentState();
+    }
+
     sp<Client> client(mClientRef.promote());
     sp<Client> newParentClient(newParent->mClientRef.promote());
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 40ebe1e..2e19b8b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -485,6 +485,11 @@
      */
     void onRemovedFromCurrentState();
 
+    /*
+     * Called when the layer is added back to the current state list.
+     */
+    void addToCurrentState();
+
     // Updates the transform hint in our SurfaceFlingerConsumer to match
     // the current orientation of the display device.
     void updateTransformHint(const sp<const DisplayDevice>& display) const;
@@ -506,7 +511,8 @@
 
     bool createHwcLayer(HWComposer* hwc, DisplayId displayId);
     bool destroyHwcLayer(DisplayId displayId);
-    void destroyAllHwcLayers();
+    void destroyHwcLayersForAllDisplays();
+    void destroyAllHwcLayersPlusChildren();
 
     bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 35ba391..43899e0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2717,6 +2717,17 @@
     }
 }
 
+void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
+    if (layer->hasReadyFrame()) {
+        const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+        if (layer->shouldPresentNow(expectedPresentTime)) {
+            bool ignored = false;
+            layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+        }
+    }
+    layer->releasePendingBuffer(systemTime());
+}
+
 void SurfaceFlinger::commitTransaction()
 {
     if (!mLayersPendingRemoval.isEmpty()) {
@@ -2730,11 +2741,9 @@
             // showing at its last configured state until we eventually
             // abandon the buffer queue.
             if (l->isRemovedFromCurrentState()) {
-                l->destroyAllHwcLayers();
-                // destroyAllHwcLayers traverses to children, but releasePendingBuffer
-                // doesn't in other scenarios. So we have to traverse explicitly here.
                 l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) {
-                    child->releasePendingBuffer(systemTime());
+                    child->destroyHwcLayersForAllDisplays();
+                    latchAndReleaseBuffer(child);
                 });
             }
         }
@@ -3171,7 +3180,7 @@
         } else {
             if (parent->isRemovedFromCurrentState()) {
                 ALOGE("addClientLayer called with a removed parent");
-                return NAME_NOT_FOUND;
+                lbc->onRemovedFromCurrentState();
             }
             parent->addChild(lbc);
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8b389bc..d42536c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -547,6 +547,7 @@
     // Can only be called from the main thread or with mStateLock held
     uint32_t setTransactionFlags(uint32_t flags);
     uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart);
+    void latchAndReleaseBuffer(const sp<Layer>& layer);
     void commitTransaction();
     bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
     uint32_t setClientStateLocked(const ComposerState& composerState);