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

Commit fcfc913c authored by Rob Carr's avatar Rob Carr Committed by Android (Google) Code Review
Browse files

Merge "SurfaceFlinger: Share ownership of layers between State and Handle."

parents 1f2aeaad 2e102c9d
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -23,7 +23,9 @@ namespace android {

BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}

BufferQueueLayer::~BufferQueueLayer() = default;
BufferQueueLayer::~BufferQueueLayer() {
    mConsumer->abandon();
}

// -----------------------------------------------------------------------
// Interface implementation for Layer
@@ -33,10 +35,6 @@ void BufferQueueLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
    mConsumer->setReleaseFence(releaseFence);
}

void BufferQueueLayer::abandon() {
    mConsumer->abandon();
}

void BufferQueueLayer::setTransformHint(uint32_t orientation) const {
    mConsumer->setTransformHint(orientation);
}
@@ -380,8 +378,18 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {

    mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
                                             item.mGraphicBuffer->getHeight(), item.mFrameNumber);
    
    // If this layer is orphaned, then we run a fake vsync pulse so that
    // dequeueBuffer doesn't block indefinitely.
    if (isRemovedFromCurrentState()) {
        bool ignored = false;
        latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
        usleep(16000);
        releasePendingBuffer(systemTime());
    } else {
        mFlinger->signalLayerUpdate();
    }
}

void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
    { // Autolock scope
+0 −2
Original line number Diff line number Diff line
@@ -40,8 +40,6 @@ public:
public:
    void onLayerDisplayed(const sp<Fence>& releaseFence) override;

    void abandon() override;

    void setTransformHint(uint32_t orientation) const override;

    std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
+38 −19
Original line number Diff line number Diff line
@@ -111,6 +111,8 @@ Layer::Layer(const LayerCreationArgs& args)
    args.flinger->getCompositorTiming(&compositorTiming);
    mFrameEventHistory.initializeCompositorTiming(compositorTiming);
    mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);

    mFlinger->onLayerCreated();
}

Layer::~Layer() {
@@ -119,13 +121,11 @@ Layer::~Layer() {
        c->detachLayer(this);
    }

    for (auto& point : mRemoteSyncPoints) {
        point->setTransactionApplied();
    }
    for (auto& point : mLocalSyncPoints) {
        point->setFrameAvailable();
    }
    mFrameTracker.logAndResetStats(mName);

    destroyAllHwcLayers();

    mFlinger->onLayerDestroyed();
}

// ---------------------------------------------------------------------------
@@ -140,10 +140,9 @@ Layer::~Layer() {
void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}

void Layer::onRemovedFromCurrentState() {
    // the layer is removed from SF mCurrentState to mLayersPendingRemoval

    mPendingRemoval = true;
    mRemovedFromCurrentState = true;

    // the layer is removed from SF mCurrentState to mLayersPendingRemoval
    if (mCurrentState.zOrderRelativeOf != nullptr) {
        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
        if (strongRelative != nullptr) {
@@ -153,19 +152,26 @@ void Layer::onRemovedFromCurrentState() {
        mCurrentState.zOrderRelativeOf = nullptr;
    }

    for (const auto& child : mCurrentChildren) {
        child->onRemovedFromCurrentState();
    }
    // Since we are no longer reachable from CurrentState SurfaceFlinger
    // will no longer invoke doTransaction for us, and so we will
    // never finish applying transactions. We signal the sync point
    // now so that another layer will not become indefinitely
    // blocked.
    for (auto& point: mRemoteSyncPoints) {
        point->setTransactionApplied();
    }
    mRemoteSyncPoints.clear();

void Layer::onRemoved() {
    // the layer is removed from SF mLayersPendingRemoval
    abandon();

    destroyAllHwcLayers();
    {
    Mutex::Autolock syncLock(mLocalSyncPointMutex);
    for (auto& point : mLocalSyncPoints) {
        point->setFrameAvailable();
    }
    mLocalSyncPoints.clear();
    }

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

@@ -228,6 +234,10 @@ void Layer::destroyAllHwcLayers() {
    }
    LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
                        "All hardware composer layers should have been destroyed");

    for (const sp<Layer>& child : mDrawingChildren) {
        child->destroyAllHwcLayers();
    }
}

Rect Layer::getContentCrop() const {
@@ -752,6 +762,9 @@ bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
        // relevant frame
        return false;
    }
    if (isRemovedFromCurrentState()) {
        return false;
    }

    Mutex::Autolock lock(mLocalSyncPointMutex);
    mLocalSyncPoints.push_back(point);
@@ -825,7 +838,9 @@ void Layer::pushPendingState() {

    // If this transaction is waiting on the receipt of a frame, generate a sync
    // point and send it to the remote layer.
    if (mCurrentState.barrierLayer_legacy != nullptr) {
    // We don't allow installing sync points after we are removed from the current state
    // as we won't be able to signal our end.
    if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
        sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote();
        if (barrierLayer == nullptr) {
            ALOGE("[%s] Unable to promote barrier Layer.", mName.string());
@@ -1994,6 +2009,10 @@ void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) {
    }
}

bool Layer::isRemovedFromCurrentState() const  {
    return mRemovedFromCurrentState;
}

// ---------------------------------------------------------------------------

}; // namespace android
+6 −12
Original line number Diff line number Diff line
@@ -346,7 +346,7 @@ public:
    virtual bool isCreatedFromMainThread() const { return false; }


    bool isPendingRemoval() const { return mPendingRemoval; }
    bool isRemovedFromCurrentState() const;

    void writeToProto(LayerProto* layerInfo,
                      LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
@@ -394,8 +394,6 @@ public:
     */
    virtual void onLayerDisplayed(const sp<Fence>& releaseFence);

    virtual void abandon() {}

    virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; }
    virtual void setTransformHint(uint32_t /*orientation*/) const { }

@@ -475,12 +473,6 @@ public:
     */
    void onRemovedFromCurrentState();

    /*
     * called with the state lock from the main thread when the layer is
     * removed from the pending removal list
     */
    void onRemoved();

    // Updates the transform hint in our SurfaceFlingerConsumer to match
    // the current orientation of the display device.
    void updateTransformHint(const sp<const DisplayDevice>& display) const;
@@ -595,12 +587,12 @@ protected:
     */
    class LayerCleaner {
        sp<SurfaceFlinger> mFlinger;
        wp<Layer> mLayer;
        sp<Layer> mLayer;

    protected:
        ~LayerCleaner() {
            // destroy client resources
            mFlinger->onLayerDestroyed(mLayer);
            mFlinger->onHandleDestroyed(mLayer);
        }

    public:
@@ -702,6 +694,8 @@ public:
    virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
    bool getPremultipledAlpha() const;

    bool mPendingHWCDestroy{false};

protected:
    // -----------------------------------------------------------------------
    bool usingRelativeZ(LayerVector::StateSet stateSet);
@@ -745,7 +739,7 @@ protected:
    // Whether filtering is needed b/c of the drawingstate
    bool mNeedsFiltering{false};

    bool mPendingRemoval{false};
    std::atomic<bool> mRemovedFromCurrentState{false};

    // page-flip thread (currently main thread)
    bool mProtectedByApp{false}; // application requires protected path to external sink
+23 −57
Original line number Diff line number Diff line
@@ -2735,7 +2735,15 @@ void SurfaceFlinger::commitTransaction()
        for (const auto& l : mLayersPendingRemoval) {
            recordBufferingStats(l->getName().string(),
                    l->getOccupancyHistory(true));
            l->onRemoved();

            // We need to release the HWC layers when the Layer is removed
            // from the current state otherwise the HWC layer just continues
            // showing at its last configured state until we eventually
            // abandon the buffer queue.
            if (l->isRemovedFromCurrentState()) {
                l->destroyAllHwcLayers();
                l->releasePendingBuffer(systemTime());
            }
        }
        mLayersPendingRemoval.clear();
    }
@@ -3168,7 +3176,7 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
        if (parent == nullptr) {
            mCurrentState.layersSortedByZ.add(lbc);
        } else {
            if (parent->isPendingRemoval()) {
            if (parent->isRemovedFromCurrentState()) {
                ALOGE("addClientLayer called with a removed parent");
                return NAME_NOT_FOUND;
            }
@@ -3184,7 +3192,6 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
                                mMaxGraphicBufferProducerListSize, mNumLayers);
        }
        mLayersAdded = true;
        mNumLayers++;
    }

    // attach this layer to the client
@@ -3198,52 +3205,22 @@ status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly)
    return removeLayerLocked(mStateLock, layer, topLevelOnly);
}

status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer,
status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer,
                                           bool topLevelOnly) {
    if (layer->isPendingRemoval()) {
        return NO_ERROR;
    }

    const auto& p = layer->getParent();
    ssize_t index;
    if (p != nullptr) {
        if (topLevelOnly) {
            return NO_ERROR;
        }

        sp<Layer> ancestor = p;
        while (ancestor->getParent() != nullptr) {
            ancestor = ancestor->getParent();
        }
        if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
            ALOGE("removeLayer called with a layer whose parent has been removed");
            return NAME_NOT_FOUND;
        }

        index = p->removeChild(layer);
    } else {
        index = mCurrentState.layersSortedByZ.remove(layer);
    }

    // As a matter of normal operation, the LayerCleaner will produce a second
    // attempt to remove the surface. The Layer will be kept alive in mDrawingState
    // so we will succeed in promoting it, but it's already been removed
    // from mCurrentState. As long as we can find it in mDrawingState we have no problem
    // otherwise something has gone wrong and we are leaking the layer.
    if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
        ALOGE("Failed to find layer (%s) in layer parent (%s).",
                layer->getName().string(),
                (p != nullptr) ? p->getName().string() : "no-parent");
        return BAD_VALUE;
    } else if (index < 0) {
        return NO_ERROR;
    }

    layer->onRemovedFromCurrentState();
    mLayersPendingRemoval.add(layer);
    mLayersRemoved = true;
    mNumLayers -= 1 + layer->getChildrenCount();
    setTransactionFlags(eTransactionNeeded);

    markLayerPendingRemovalLocked(lock, layer);
    return NO_ERROR;
}

@@ -3444,11 +3421,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState
        return 0;
    }

    if (layer->isPendingRemoval()) {
        ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
        return 0;
    }

    uint32_t flags = 0;

    const uint32_t what = s.what;
@@ -3652,11 +3624,6 @@ void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) {
        return;
    }

    if (layer->isPendingRemoval()) {
        ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string());
        return;
    }

    if (state.what & layer_state_t::eDestroySurface) {
        removeLayerLocked(mStateLock, layer);
    }
@@ -3830,17 +3797,16 @@ status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBind
    return err;
}

status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
{
    // called by ~LayerCleaner() when all references to the IBinder (handle)
    // are gone
    sp<Layer> l = layer.promote();
    if (l == nullptr) {
        // The layer has already been removed, carry on
        return NO_ERROR;
void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp<Layer>& layer) {
    mLayersPendingRemoval.add(layer);
    mLayersRemoved = true;
    setTransactionFlags(eTransactionNeeded);
}
    // If we have a parent, then we can continue to live as long as it does.
    return removeLayer(l, true);

void SurfaceFlinger::onHandleDestroyed(const sp<Layer>& layer)
{
    Mutex::Autolock lock(mStateLock);
    markLayerPendingRemovalLocked(mStateLock, layer);
}

// ---------------------------------------------------------------------------
@@ -5189,7 +5155,7 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
    auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
    auto parent = layerHandle->owner.promote();

    if (parent == nullptr || parent->isPendingRemoval()) {
    if (parent == nullptr || parent->isRemovedFromCurrentState()) {
        ALOGE("captureLayers called with a removed parent");
        return NAME_NOT_FOUND;
    }
Loading