Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cec3ed2 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

[sf] Properly update clones of clones

When updating a cloned layer hierarchy that contains
another cloned layer hierarchy, we are dependent on
the order in which we update each hierarchy.
The inner cloned hierarchy must be updated first
otherwise the outer clone will not capture the entire
tree and some layers might be omitted from
composition.
To fix this we track all layer mirror roots. When updating
each root, we check to see if they mirror another root. If
they do mirror another root and that root has not been updated,
we update the root again at the end.

Test: repro steps in bug
Fixes: 279622227
Change-Id: I07e3f2c89d62d44455fda9fe3f8203215c22abf7
parent 8bf29931
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -254,7 +254,8 @@ Layer::~Layer() {
        mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
    }
    if (mHadClonedChild) {
        mFlinger->mNumClones--;
        auto& roots = mFlinger->mLayerMirrorRoots;
        roots.erase(std::remove(roots.begin(), roots.end(), this), roots.end());
    }
    if (hasTrustedPresentationListener()) {
        mFlinger->mNumTrustedPresentationListeners--;
@@ -2591,7 +2592,7 @@ void Layer::updateCloneBufferInfo() {
    mDrawingState.inputInfo = tmpInputInfo;
}

void Layer::updateMirrorInfo() {
bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) {
    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
@@ -2599,7 +2600,7 @@ void Layer::updateMirrorInfo() {
        // 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;
        return true;
    }

    std::map<sp<Layer>, sp<Layer>> clonedLayersMap;
@@ -2614,6 +2615,13 @@ void Layer::updateMirrorInfo() {
    mClonedChild->updateClonedDrawingState(clonedLayersMap);
    mClonedChild->updateClonedChildren(sp<Layer>::fromExisting(this), clonedLayersMap);
    mClonedChild->updateClonedRelatives(clonedLayersMap);

    for (Layer* root : cloneRootsPendingUpdates) {
        if (clonedLayersMap.find(sp<Layer>::fromExisting(root)) != clonedLayersMap.end()) {
            return false;
        }
    }
    return true;
}

void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
@@ -2761,7 +2769,7 @@ bool Layer::isInternalDisplayOverlay() const {
void Layer::setClonedChild(const sp<Layer>& clonedChild) {
    mClonedChild = clonedChild;
    mHadClonedChild = true;
    mFlinger->mNumClones++;
    mFlinger->mLayerMirrorRoots.push_back(this);
}

bool Layer::setDropInputMode(gui::DropInputMode mode) {
+1 −1
Original line number Diff line number Diff line
@@ -651,7 +651,7 @@ public:

    gui::WindowInfo::Type getWindowType() const { return mWindowType; }

    void updateMirrorInfo();
    bool updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates);

    /*
     * doTransaction - process the transaction. This is a good place to figure
+1 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ void LayerRenderArea::render(std::function<void()> drawLayers) {
    // If layer is offscreen, update mirroring info if it exists
    if (mLayer->isRemovedFromCurrentState()) {
        mLayer->traverse(LayerVector::StateSet::Drawing,
                         [&](Layer* layer) { layer->updateMirrorInfo(); });
                         [&](Layer* layer) { layer->updateMirrorInfo({}); });
        mLayer->traverse(LayerVector::StateSet::Drawing,
                         [&](Layer* layer) { layer->updateCloneBufferInfo(); });
    }
+16 −3
Original line number Diff line number Diff line
@@ -4007,8 +4007,21 @@ void SurfaceFlinger::doCommitTransactions() {
    }

    commitOffscreenLayers();
    if (mNumClones > 0) {
        mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
    if (mLayerMirrorRoots.size() > 0) {
        std::deque<Layer*> pendingUpdates;
        pendingUpdates.insert(pendingUpdates.end(), mLayerMirrorRoots.begin(),
                              mLayerMirrorRoots.end());
        std::vector<Layer*> needsUpdating;
        for (Layer* cloneRoot : mLayerMirrorRoots) {
            pendingUpdates.pop_front();
            if (cloneRoot->updateMirrorInfo(pendingUpdates)) {
            } else {
                needsUpdating.push_back(cloneRoot);
            }
        }
        for (Layer* cloneRoot : needsUpdating) {
            cloneRoot->updateMirrorInfo({});
        }
    }
}

@@ -4115,7 +4128,7 @@ bool SurfaceFlinger::latchBuffers() {
        mBootStage = BootStage::BOOTANIMATION;
    }

    if (mNumClones > 0) {
    if (mLayerMirrorRoots.size() > 0) {
        mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
    }

+1 −2
Original line number Diff line number Diff line
@@ -296,8 +296,7 @@ public:
    // the client can no longer modify this layer directly.
    void onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId);

    // TODO: Remove atomic if move dtor to main thread CL lands
    std::atomic<uint32_t> mNumClones;
    std::vector<Layer*> mLayerMirrorRoots;

    TransactionCallbackInvoker& getTransactionCallbackInvoker() {
        return mTransactionCallbackInvoker;