[Mirror Layers] Added functions to update mirrored layers info (2/4)
Added updateMirrorInfo and updateBufferInfoFromClone to ensure the state
and buffer of the clones are updated properly. updateMirrorInfo is
called when commitTransaction is called to update the drawing state,
children, and relatives. updateBufferInfoFromClone is called in
handlePageFlip after the real layer calls latchBuffer to ensure the
cloned layer gets the updated buffer and buffer info.
Test: No mirror request yet so everything runs normally
Bug: 131622422
Change-Id: Ic2b1f66cab98175dbdccf90f2f8310c7f19d8cff
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d189846..b500ad3 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -295,7 +295,7 @@
const CompositorTiming& compositorTiming) {
// mFrameLatencyNeeded is true when a new frame was latched for the
// composition.
- if (!mFrameLatencyNeeded) return false;
+ if (!mBufferInfo.mFrameLatencyNeeded) return false;
// Update mFrameEventHistory.
{
@@ -337,7 +337,7 @@
}
mFrameTracker.advanceFrame();
- mFrameLatencyNeeded = false;
+ mBufferInfo.mFrameLatencyNeeded = false;
return true;
}
@@ -401,7 +401,7 @@
gatherBufferInfo();
mRefreshPending = true;
- mFrameLatencyNeeded = true;
+ mBufferInfo.mFrameLatencyNeeded = true;
if (oldBufferInfo.mBuffer == nullptr) {
// the first time we receive a buffer, we need to trigger a
// geometry invalidation.
@@ -735,6 +735,35 @@
mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha;
mPotentialCursor = bufferClonedFrom->mPotentialCursor;
mProtectedByApp = bufferClonedFrom->mProtectedByApp;
+
+ updateCloneBufferInfo();
+}
+
+void BufferLayer::updateCloneBufferInfo() {
+ if (!isClone() || !isClonedFromAlive()) {
+ return;
+ }
+
+ sp<BufferLayer> clonedFrom = static_cast<BufferLayer*>(getClonedFrom().get());
+ mBufferInfo = clonedFrom->mBufferInfo;
+ mSidebandStream = clonedFrom->mSidebandStream;
+ surfaceDamageRegion = clonedFrom->surfaceDamageRegion;
+ mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load();
+ mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber;
+
+ // After buffer info is updated, the drawingState from the real layer needs to be copied into
+ // the cloned. This is because some properties of drawingState can change when latchBuffer is
+ // called. However, copying the drawingState would also overwrite the cloned layer's relatives.
+ // Therefore, temporarily store the relatives so they can be set in the cloned drawingState
+ // again.
+ wp<Layer> tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf;
+ SortedVector<wp<Layer>> tmpZOrderRelatives = mDrawingState.zOrderRelatives;
+ mDrawingState = clonedFrom->mDrawingState;
+ // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple
+ // InputWindows per client token yet.
+ mDrawingState.inputInfo.token = nullptr;
+ mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf;
+ mDrawingState.zOrderRelatives = tmpZOrderRelatives;
}
} // namespace android
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index b2c0618..656ba12 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -165,6 +165,8 @@
sp<GraphicBuffer> mBuffer;
int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
+
+ bool mFrameLatencyNeeded{false};
};
BufferInfo mBufferInfo;
@@ -195,6 +197,8 @@
ui::Dataspace translateDataspace(ui::Dataspace dataspace);
void setInitialValuesForClone(const sp<Layer>& clonedFrom);
+ void updateCloneBufferInfo() override;
+ uint64_t mPreviousFrameNumber = 0;
private:
// Returns true if this layer requires filtering
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 36dff15..f3e8a19 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -111,8 +111,6 @@
PixelFormat mFormat{PIXEL_FORMAT_NONE};
- // Only accessed on the main thread.
- uint64_t mPreviousFrameNumber{0};
bool mUpdateTexImageFailed{false};
uint64_t mPreviousBufferId = 0;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index e951ccf..3dfe76c 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -143,7 +143,6 @@
sp<Fence> mPreviousReleaseFence;
uint64_t mPreviousBufferId = 0;
- uint64_t mPreviousFrameNumber = 0;
uint64_t mPreviousReleasedFrameNumber = 0;
mutable bool mCurrentStateModified = false;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 079bc66..f017ca0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2025,6 +2025,118 @@
// InputWindows per client token yet.
mDrawingState.inputInfo.token = nullptr;
}
+
+void Layer::updateMirrorInfo() {
+ if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) {
+ // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false,
+ // it means that there is a clone, but the layer it was cloned from has been destroyed. In
+ // that case, we want to delete the reference to the clone since we want it to get
+ // destroyed. The root, this layer, will still be around since the client can continue
+ // to hold a reference, but no cloned layers will be displayed.
+ mClonedChild = nullptr;
+ return;
+ }
+
+ std::map<sp<Layer>, sp<Layer>> clonedLayersMap;
+ // If the real layer exists and is in current state, add the clone as a child of the root.
+ // There's no need to remove from drawingState when the layer is offscreen since currentState is
+ // copied to drawingState for the root layer. So the clonedChild is always removed from
+ // drawingState and then needs to be added back each traversal.
+ if (!mClonedChild->getClonedFrom()->isRemovedFromCurrentState()) {
+ addChildToDrawing(mClonedChild);
+ }
+
+ mClonedChild->updateClonedDrawingState(clonedLayersMap);
+ mClonedChild->updateClonedChildren(this, clonedLayersMap);
+ mClonedChild->updateClonedRelatives(clonedLayersMap);
+}
+
+void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
+ // If the layer the clone was cloned from is alive, copy the content of the drawingState
+ // to the clone. If the real layer is no longer alive, continue traversing the children
+ // since we may be able to pull out other children that are still alive.
+ if (isClonedFromAlive()) {
+ sp<Layer> clonedFrom = getClonedFrom();
+ mDrawingState = clonedFrom->mDrawingState;
+ // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple
+ // InputWindows per client token yet.
+ mDrawingState.inputInfo.token = nullptr;
+ clonedLayersMap.emplace(clonedFrom, this);
+ }
+
+ // The clone layer may have children in drawingState since they may have been created and
+ // added from a previous request to updateMirorInfo. This is to ensure we don't recreate clones
+ // that already exist, since we can just re-use them.
+ // The drawingChildren will not get overwritten by the currentChildren since the clones are
+ // not updated in the regular traversal. They are skipped since the root will lose the
+ // reference to them when it copies its currentChildren to drawing.
+ for (sp<Layer>& child : mDrawingChildren) {
+ child->updateClonedDrawingState(clonedLayersMap);
+ }
+}
+
+void Layer::updateClonedChildren(const sp<Layer>& mirrorRoot,
+ std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
+ mDrawingChildren.clear();
+
+ if (!isClonedFromAlive()) {
+ return;
+ }
+
+ sp<Layer> clonedFrom = getClonedFrom();
+ for (sp<Layer>& child : clonedFrom->mDrawingChildren) {
+ if (child == mirrorRoot) {
+ // This is to avoid cyclical mirroring.
+ continue;
+ }
+ sp<Layer> clonedChild = clonedLayersMap[child];
+ if (clonedChild == nullptr) {
+ clonedChild = child->createClone();
+ clonedLayersMap[child] = clonedChild;
+ }
+ addChildToDrawing(clonedChild);
+ clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap);
+ }
+}
+
+void Layer::updateClonedRelatives(std::map<sp<Layer>, sp<Layer>> clonedLayersMap) {
+ mDrawingState.zOrderRelativeOf = nullptr;
+ mDrawingState.zOrderRelatives.clear();
+
+ if (!isClonedFromAlive()) {
+ return;
+ }
+
+ sp<Layer> clonedFrom = getClonedFrom();
+ for (wp<Layer>& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) {
+ sp<Layer> relative = relativeWeak.promote();
+ auto clonedRelative = clonedLayersMap[relative];
+ if (clonedRelative != nullptr) {
+ mDrawingState.zOrderRelatives.add(clonedRelative);
+ }
+ }
+
+ // Check if the relativeLayer for the real layer is part of the cloned hierarchy.
+ // It's possible that the layer it's relative to is outside the requested cloned hierarchy.
+ // In that case, we treat the layer as if the relativeOf has been removed. This way, it will
+ // still traverse the children, but the layer with the missing relativeOf will not be shown
+ // on screen.
+ sp<Layer> relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote();
+ sp<Layer> clonedRelativeOf = clonedLayersMap[relativeOf];
+ if (clonedRelativeOf != nullptr) {
+ mDrawingState.zOrderRelativeOf = clonedRelativeOf;
+ }
+
+ for (sp<Layer>& child : mDrawingChildren) {
+ child->updateClonedRelatives(clonedLayersMap);
+ }
+}
+
+void Layer::addChildToDrawing(const sp<Layer>& layer) {
+ mDrawingChildren.add(layer);
+ layer->mDrawingParent = this;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 610df25..3023cf5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -468,13 +468,30 @@
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; }
-protected:
- virtual sp<Layer> createClone() = 0;
- sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; }
+ // This layer is not a clone, but it's the parent to the cloned hierarchy. The
+ // variable mClonedChild represents the top layer that will be cloned so this
+ // layer will be the parent of mClonedChild.
+ // The layers in the cloned hierarchy will match the lifetime of the real layers. That is
+ // if the real layer is destroyed, then the clone layer will also be destroyed.
+ sp<Layer> mClonedChild;
- bool isClone() { return getClonedFrom() != nullptr; }
+ virtual sp<Layer> createClone() = 0;
+ void updateMirrorInfo();
+ virtual void updateCloneBufferInfo(){};
+
+protected:
+ sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; }
+ bool isClone() { return mClonedFrom != nullptr; }
+ bool isClonedFromAlive() { return getClonedFrom() != nullptr; }
+
virtual void setInitialValuesForClone(const sp<Layer>& clonedFrom);
+ void updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap);
+ void updateClonedChildren(const sp<Layer>& mirrorRoot,
+ std::map<sp<Layer>, sp<Layer>>& clonedLayersMap);
+ void updateClonedRelatives(std::map<sp<Layer>, sp<Layer>> clonedLayersMap);
+ void addChildToDrawing(const sp<Layer>& layer);
+
public:
/*
* compositionengine::LayerFE overrides
@@ -838,7 +855,6 @@
// We encode unset as -1.
int32_t mOverrideScalingMode{-1};
std::atomic<uint64_t> mCurrentFrameNumber{0};
- bool mFrameLatencyNeeded{false};
// Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering{false};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8699747..86e73c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2600,6 +2600,7 @@
});
commitOffscreenLayers();
+ mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateMirrorInfo(); });
}
void SurfaceFlinger::withTracingLock(std::function<void()> lockedOperation) {
@@ -2718,6 +2719,8 @@
mBootStage = BootStage::BOOTANIMATION;
}
+ mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateCloneBufferInfo(); });
+
// Only continue with the refresh if there is actually new work to do
return !mLayersWithQueuedFrames.empty() && newDataLatched;
}