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

Commit 61626f2e authored by chaviw's avatar chaviw
Browse files

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
parent 2df4fb0e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ BufferLayer::~BufferLayer() {
        ALOGE("Found stale hardware composer layers when destroying "
              "surface flinger layer %s",
              mName.string());
        destroyAllHwcLayers();
        destroyAllHwcLayersPlusChildren();
    }

    mTimeStats.onDestroy(getSequence());
+19 −3
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ Layer::~Layer() {

    mFrameTracker.logAndResetStats(mName);

    destroyAllHwcLayers();
    destroyAllHwcLayersPlusChildren();

    mFlinger->onLayerDestroyed();
}
@@ -175,6 +175,14 @@ void Layer::onRemovedFromCurrentState() {
    }
}

void Layer::addToCurrentState() {
    mRemovedFromCurrentState = false;

    for (const auto& child : mCurrentChildren) {
        child->addToCurrentState();
    }
}

// ---------------------------------------------------------------------------
// set-up
// ---------------------------------------------------------------------------
@@ -226,17 +234,21 @@ bool Layer::destroyHwcLayer(DisplayId displayId) {
    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 @@ bool Layer::reparent(const sp<IBinder>& newParentHandle) {
    }
    newParent->addChild(this);

    if (!newParent->isRemovedFromCurrentState()) {
        addToCurrentState();
    }

    sp<Client> client(mClientRef.promote());
    sp<Client> newParentClient(newParent->mClientRef.promote());

+7 −1
Original line number Diff line number Diff line
@@ -485,6 +485,11 @@ public:
     */
    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 @@ public:

    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; }

+14 −5
Original line number Diff line number Diff line
@@ -2717,6 +2717,17 @@ void SurfaceFlinger::updateCursorAsync()
    }
}

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 @@ void SurfaceFlinger::commitTransaction()
            // 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 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
        } else {
            if (parent->isRemovedFromCurrentState()) {
                ALOGE("addClientLayer called with a removed parent");
                return NAME_NOT_FOUND;
                lbc->onRemovedFromCurrentState();
            }
            parent->addChild(lbc);
        }
+1 −0
Original line number Diff line number Diff line
@@ -547,6 +547,7 @@ private:
    // 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);