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

Commit e5374e50 authored by Dorin Drimus's avatar Dorin Drimus
Browse files

Clear unexpected buffer handle of sideband layer

If the buffer handle is not cleared after MediaCodec disconnected
and the surface is re-used for another sideband stream. SurfaceFlinger
would trigger incorrect composition type change from sideband to
device when SurfaceView layout changed.

Clear the buffer if the layer was about to set a new sideband
handle.

Bug: 291202822
Test: Adjust the screen layout after played 2 different sideband
stream. No composition type change.

Change-Id: I0b42d68ea03fb09db9aefc257d6071e559a3d8d2
parent 32295332
Loading
Loading
Loading
Loading
+41 −24
Original line number Diff line number Diff line
@@ -3092,6 +3092,32 @@ bool Layer::setPosition(float x, float y) {
    return true;
}

void Layer::releasePreviousBuffer() {
    mReleasePreviousBuffer = true;
    if (!mBufferInfo.mBuffer ||
        (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
         mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
        // If mDrawingState has a buffer, and we are about to update again
        // before swapping to drawing state, then the first buffer will be
        // dropped and we should decrement the pending buffer count and
        // call any release buffer callbacks if set.
        callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                  mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
                                  mDrawingState.acquireFence);
        decrementPendingBufferCount();
        if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
            mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
            addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
            mDrawingState.bufferSurfaceFrameTX.reset();
        }
    } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
        callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                  mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
                                  mLastClientCompositionFence);
        mLastClientCompositionFence = nullptr;
    }
}

void Layer::resetDrawingStateBufferInfo() {
    mDrawingState.producerId = 0;
    mDrawingState.frameNumber = 0;
@@ -3116,29 +3142,7 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
    ATRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber);

    if (mDrawingState.buffer) {
        mReleasePreviousBuffer = true;
        if (!mBufferInfo.mBuffer ||
            (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
             mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
            // If mDrawingState has a buffer, and we are about to update again
            // before swapping to drawing state, then the first buffer will be
            // dropped and we should decrement the pending buffer count and
            // call any release buffer callbacks if set.
            callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                      mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
                                      mDrawingState.acquireFence);
            decrementPendingBufferCount();
            if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
                mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
                addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
                mDrawingState.bufferSurfaceFrameTX.reset();
            }
        } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
            callReleaseBufferCallback(mDrawingState.releaseBufferListener,
                                      mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
                                      mLastClientCompositionFence);
            mLastClientCompositionFence = nullptr;
        }
        releasePreviousBuffer();
    } else if (buffer) {
        // if we are latching a buffer for the first time then clear the mLastLatchTime since
        // we don't want to incorrectly classify a frame if we miss the desired present time.
@@ -3156,6 +3160,12 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
        mDrawingState.bufferSurfaceFrameTX = nullptr;
        setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
        return true;
    } else {
        // release sideband stream if it exists and a non null buffer is being set
        if (mDrawingState.sidebandStream != nullptr) {
            mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
            mDrawingState.sidebandStream = nullptr;
        }
    }

    if ((mDrawingState.producerId > bufferData.producerId) ||
@@ -3344,7 +3354,8 @@ bool Layer::setApi(int32_t api) {
    return true;
}

bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream, const FrameTimelineInfo& info,
                              nsecs_t postTime) {
    if (mDrawingState.sidebandStream == sidebandStream) return false;

    if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
@@ -3355,6 +3366,12 @@ bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {

    mDrawingState.sidebandStream = sidebandStream;
    mDrawingState.modified = true;
    if (sidebandStream != nullptr && mDrawingState.buffer != nullptr) {
        releasePreviousBuffer();
        resetDrawingStateBufferInfo();
        mDrawingState.bufferSurfaceFrameTX = nullptr;
        setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
    }
    setTransactionFlags(eTransactionNeeded);
    if (!mSidebandStreamChanged.exchange(true)) {
        // mSidebandStreamChanged was false
+3 −1
Original line number Diff line number Diff line
@@ -317,7 +317,8 @@ public:
    bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/);
    bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/);
    bool setApi(int32_t /*api*/);
    bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/);
    bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/,
                           const FrameTimelineInfo& /* info*/, nsecs_t /* postTime */);
    bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& /*handles*/,
                                          bool willPresent);
    virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace)
@@ -1204,6 +1205,7 @@ private:
    half4 mBorderColor;

    void setTransformHintLegacy(ui::Transform::RotationFlags);
    void releasePreviousBuffer();
    void resetDrawingStateBufferInfo();

    // Transform hint provided to the producer. This must be accessed holding
+4 −2
Original line number Diff line number Diff line
@@ -5139,7 +5139,8 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime
        if (layer->setApi(s.api)) flags |= eTraversalNeeded;
    }
    if (what & layer_state_t::eSidebandStreamChanged) {
        if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
        if (layer->setSidebandStream(s.sidebandStream, frameTimelineInfo, postTime))
            flags |= eTraversalNeeded;
    }
    if (what & layer_state_t::eInputInfoChanged) {
        layer->setInputInfo(*s.windowInfoHandle->getInfo());
@@ -5383,7 +5384,8 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f
        if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
    }
    if (what & layer_state_t::eSidebandStreamChanged) {
        if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
        if (layer->setSidebandStream(s.sidebandStream, frameTimelineInfo, postTime))
            flags |= eTraversalNeeded;
    }
    if (what & layer_state_t::eDataspaceChanged) {
        if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded;
+2 −1
Original line number Diff line number Diff line
@@ -153,7 +153,8 @@ void LayerFuzzer::invokeBufferStateLayer() {
    native_handle_t* testHandle = native_handle_create(0, 1);
    const bool ownsHandle = mFdp.ConsumeBool();
    sp<NativeHandle> nativeHandle = sp<NativeHandle>::make(testHandle, ownsHandle);
    layer->setSidebandStream(nativeHandle);
    layer->setSidebandStream(nativeHandle, getFuzzedFrameTimelineInfo(),
                             mFdp.ConsumeIntegral<nsecs_t>() /* postTime */);
    layer->computeSourceBounds(getFuzzedFloatRect(&mFdp));

    layer->fenceHasSignaled();
+2 −2
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ TEST_F(TunnelModeEnabledReporterTest, callsNewListenerWithFreshInformation) {
    sp<NativeHandle> stream =
            NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
                                 false);
    layer->setSidebandStream(stream);
    layer->setSidebandStream(stream, FrameTimelineInfo{}, 20);
    mFlinger.mutableCurrentState().layersSortedByZ.add(layer);
    mTunnelModeEnabledReporter->updateTunnelModeStatus();
    mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
@@ -151,7 +151,7 @@ TEST_F(TunnelModeEnabledReporterTest, layerWithSidebandStreamTriggersUpdate) {
    sp<NativeHandle> stream =
            NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
                                 false);
    layerWithSidebandStream->setSidebandStream(stream);
    layerWithSidebandStream->setSidebandStream(stream, FrameTimelineInfo{}, 20);

    mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer);
    mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream);