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

Commit 2b84a2e2 authored by Satish Yalla's avatar Satish Yalla Committed by Android (Google) Code Review
Browse files

Merge "Revert^3 "Read from BufferReleaseChannel in background thread"" into main

parents 629686cd 4aface1c
Loading
Loading
Loading
Loading
+10 −151
Original line number Diff line number Diff line
@@ -22,14 +22,11 @@

#include <com_android_graphics_libgui_flags.h>
#include <cutils/atomic.h>
#include <ftl/fake_guard.h>
#include <gui/BLASTBufferQueue.h>
#include <gui/BufferItemConsumer.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>

#include <gui/FrameRateUtils.h>
#include <gui/GLConsumer.h>
@@ -77,12 +74,6 @@ namespace android {
    std::unique_lock _lock{mutex};        \
    base::ScopedLockAssertion assumeLocked(mutex);

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
static ReleaseBufferCallback EMPTY_RELEASE_CALLBACK =
        [](const ReleaseCallbackId&, const sp<Fence>& /*releaseFence*/,
           std::optional<uint32_t> /*currentMaxAcquiredBufferCount*/) {};
#endif

void BLASTBufferItemConsumer::onDisconnect() {
    Mutex::Autolock lock(mMutex);
    mPreviouslyConnected = mCurrentlyConnected;
@@ -224,12 +215,6 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinati
            },
            this);

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> bufferReleaseConsumer;
    gui::BufferReleaseChannel::open(mName, bufferReleaseConsumer, mBufferReleaseProducer);
    mBufferReleaseReader = std::make_shared<BufferReleaseReader>(std::move(bufferReleaseConsumer));
#endif

    BQA_LOGV("BLASTBufferQueue created");
}

@@ -259,9 +244,6 @@ BLASTBufferQueue::~BLASTBufferQueue() {
void BLASTBufferQueue::onFirstRef() {
    // safe default, most producers are expected to override this
    mProducer->setMaxDequeuedBufferCount(2);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    mBufferReleaseThread.start(sp<BLASTBufferQueue>::fromExisting(this));
#endif
}

void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
@@ -287,9 +269,6 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    if (surfaceControlChanged) {
        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
                   layer_state_t::eEnableBackpressure);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
        t.setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer);
#endif
        applyTransaction = true;
    }
    mTransformHint = mSurfaceControl->getTransformHint();
@@ -407,7 +386,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                    stat.latchTime,
                                                    stat.frameEventStats.dequeueReadyTime);
                }
#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
                auto currFrameNumber = stat.frameEventStats.frameNumber;
                std::vector<ReleaseCallbackId> staleReleases;
                for (const auto& [key, value]: mSubmitted) {
@@ -423,7 +401,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                stat.currentMaxAcquiredBufferCount,
                                                true /* fakeRelease */);
                }
#endif
            } else {
                BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
            }
@@ -434,15 +411,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
    }
}

void BLASTBufferQueue::flushShadowQueue() {
    BQA_LOGV("flushShadowQueue");
    int numFramesToFlush = mNumFrameAvailable;
    while (numFramesToFlush > 0) {
        acquireNextBufferLocked(std::nullopt);
        numFramesToFlush--;
    }
}

// Unlike transactionCallbackThunk the release buffer callback does not extend the life of the
// BBQ. This is because if the BBQ is destroyed, then the buffers will be released by the client.
// So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer.
@@ -460,6 +428,15 @@ ReleaseBufferCallback BLASTBufferQueue::makeReleaseBufferCallbackThunk() {
    };
}

void BLASTBufferQueue::flushShadowQueue() {
    BQA_LOGV("flushShadowQueue");
    int numFramesToFlush = mNumFrameAvailable;
    while (numFramesToFlush > 0) {
        acquireNextBufferLocked(std::nullopt);
        numFramesToFlush--;
    }
}

void BLASTBufferQueue::releaseBufferCallback(
        const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
        std::optional<uint32_t> currentMaxAcquiredBufferCount) {
@@ -634,12 +611,7 @@ status_t BLASTBufferQueue::acquireNextBufferLocked(
                           bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
                           bufferItem.mScalingMode, crop);

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    ReleaseBufferCallback releaseBufferCallback =
            applyTransaction ? EMPTY_RELEASE_CALLBACK : makeReleaseBufferCallbackThunk();
#else
    auto releaseBufferCallback = makeReleaseBufferCallbackThunk();
#endif
    sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;

    nsecs_t dequeueTime = -1;
@@ -1252,120 +1224,7 @@ bool BLASTBufferQueue::isSameSurfaceControl(const sp<SurfaceControl>& surfaceCon
void BLASTBufferQueue::setTransactionHangCallback(
        std::function<void(const std::string&)> callback) {
    std::lock_guard _lock{mMutex};
    mTransactionHangCallback = std::move(callback);
    mTransactionHangCallback = callback;
}

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)

BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(
        std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> endpoint)
      : mEndpoint{std::move(endpoint)} {
    mEpollFd = android::base::unique_fd{epoll_create1(0)};
    LOG_ALWAYS_FATAL_IF(!mEpollFd.ok(),
                        "Failed to create buffer release epoll file descriptor. errno=%d "
                        "message='%s'",
                        errno, strerror(errno));

    epoll_event registerEndpointFd{};
    registerEndpointFd.events = EPOLLIN;
    registerEndpointFd.data.fd = mEndpoint->getFd();
    status_t status =
            epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mEndpoint->getFd(), &registerEndpointFd);
    LOG_ALWAYS_FATAL_IF(status == -1,
                        "Failed to register buffer release consumer file descriptor with epoll. "
                        "errno=%d message='%s'",
                        errno, strerror(errno));

    mEventFd = android::base::unique_fd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
    LOG_ALWAYS_FATAL_IF(!mEventFd.ok(),
                        "Failed to create buffer release event file descriptor. errno=%d "
                        "message='%s'",
                        errno, strerror(errno));

    epoll_event registerEventFd{};
    registerEventFd.events = EPOLLIN;
    registerEventFd.data.fd = mEventFd.get();
    status = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mEventFd.get(), &registerEventFd);
    LOG_ALWAYS_FATAL_IF(status == -1,
                        "Failed to register buffer release event file descriptor with epoll. "
                        "errno=%d message='%s'",
                        errno, strerror(errno));
}

BLASTBufferQueue::BufferReleaseReader& BLASTBufferQueue::BufferReleaseReader::operator=(
        BufferReleaseReader&& other) {
    if (this != &other) {
        ftl::FakeGuard guard{mMutex};
        ftl::FakeGuard otherGuard{other.mMutex};
        mEndpoint = std::move(other.mEndpoint);
        mEpollFd = std::move(other.mEpollFd);
        mEventFd = std::move(other.mEventFd);
    }
    return *this;
}

status_t BLASTBufferQueue::BufferReleaseReader::readBlocking(ReleaseCallbackId& outId,
                                                             sp<Fence>& outFence,
                                                             uint32_t& outMaxAcquiredBufferCount) {
    epoll_event event{};
    while (true) {
        int eventCount = epoll_wait(mEpollFd.get(), &event, 1 /* maxevents */, -1 /* timeout */);
        if (eventCount == 1) {
            break;
        }
        if (eventCount == -1 && errno != EINTR) {
            ALOGE("epoll_wait error while waiting for buffer release. errno=%d message='%s'", errno,
                  strerror(errno));
        }
    }

    if (event.data.fd == mEventFd.get()) {
        uint64_t value;
        if (read(mEventFd.get(), &value, sizeof(uint64_t)) == -1 && errno != EWOULDBLOCK) {
            ALOGE("error while reading from eventfd. errno=%d message='%s'", errno,
                  strerror(errno));
        }
        return WOULD_BLOCK;
    }

    std::lock_guard lock{mMutex};
    return mEndpoint->readReleaseFence(outId, outFence, outMaxAcquiredBufferCount);
}

void BLASTBufferQueue::BufferReleaseReader::interruptBlockingRead() {
    uint64_t value = 1;
    if (write(mEventFd.get(), &value, sizeof(uint64_t)) == -1) {
        ALOGE("failed to notify dequeue event. errno=%d message='%s'", errno, strerror(errno));
    }
}

void BLASTBufferQueue::BufferReleaseThread::start(const sp<BLASTBufferQueue>& bbq) {
    mRunning = std::make_shared<std::atomic_bool>(true);
    mReader = bbq->mBufferReleaseReader;
    std::thread([running = mRunning, reader = mReader, weakBbq = wp<BLASTBufferQueue>(bbq)]() {
        pthread_setname_np(pthread_self(), "BufferReleaseThread");
        while (*running) {
            ReleaseCallbackId id;
            sp<Fence> fence;
            uint32_t maxAcquiredBufferCount;
            if (status_t status = reader->readBlocking(id, fence, maxAcquiredBufferCount);
                status != OK) {
                continue;
            }
            sp<BLASTBufferQueue> bbq = weakBbq.promote();
            if (!bbq) {
                return;
            }
            bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
        }
    }).detach();
}

BLASTBufferQueue::BufferReleaseThread::~BufferReleaseThread() {
    *mRunning = false;
    mReader->interruptBlockingRead();
}

#endif

} // namespace android
+0 −45
Original line number Diff line number Diff line
@@ -315,51 +315,6 @@ private:
    std::function<void(const std::string&)> mTransactionHangCallback;

    std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    class BufferReleaseReader {
    public:
        BufferReleaseReader() = default;
        BufferReleaseReader(std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint>);
        BufferReleaseReader& operator=(BufferReleaseReader&&);

        // Block until we can read a buffer release message.
        //
        // Returns:
        // * OK if a ReleaseCallbackId and Fence were successfully read.
        // * WOULD_BLOCK if the blocking read was interrupted by interruptBlockingRead.
        // * UNKNOWN_ERROR if something went wrong.
        status_t readBlocking(ReleaseCallbackId& outId, sp<Fence>& outReleaseFence,
                              uint32_t& outMaxAcquiredBufferCount);

        // Signals the reader's eventfd to wake up any threads waiting on readBlocking.
        void interruptBlockingRead();

    private:
        std::mutex mMutex;
        std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mEndpoint GUARDED_BY(mMutex);
        android::base::unique_fd mEpollFd;
        android::base::unique_fd mEventFd;
    };

    // BufferReleaseChannel is used to communicate buffer releases from SurfaceFlinger to
    // the client. See BBQBufferQueueProducer::dequeueBuffer for details.
    std::shared_ptr<BufferReleaseReader> mBufferReleaseReader;
    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;

    class BufferReleaseThread {
    public:
        BufferReleaseThread() = default;
        ~BufferReleaseThread();
        void start(const sp<BLASTBufferQueue>&);

    private:
        std::shared_ptr<std::atomic_bool> mRunning;
        std::shared_ptr<BufferReleaseReader> mReader;
    };

    BufferReleaseThread mBufferReleaseThread;
#endif
};

} // namespace android
+4 −19
Original line number Diff line number Diff line
@@ -1951,24 +1951,15 @@ bool Layer::setDropInputMode(gui::DropInputMode mode) {
void Layer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
                                      const sp<GraphicBuffer>& buffer, uint64_t framenumber,
                                      const sp<Fence>& releaseFence) {
    if (!listener && !mBufferReleaseChannel) {
    if (!listener) {
        return;
    }

    SFTRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber);

    ReleaseCallbackId callbackId{buffer->getId(), framenumber};
    const sp<Fence>& fence = releaseFence ? releaseFence : Fence::NO_FENCE;
    uint32_t currentMaxAcquiredBufferCount =
            mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);

    if (listener) {
        listener->onReleaseBuffer(callbackId, fence, currentMaxAcquiredBufferCount);
    }

    if (mBufferReleaseChannel) {
        mBufferReleaseChannel->writeReleaseFence(callbackId, fence, currentMaxAcquiredBufferCount);
    }
    listener->onReleaseBuffer({buffer->getId(), framenumber},
                              releaseFence ? releaseFence : Fence::NO_FENCE,
                              currentMaxAcquiredBufferCount);
}

sp<CallbackHandle> Layer::findCallbackHandle() {
@@ -2086,7 +2077,6 @@ void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,

void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
    for (const auto& handle : mDrawingState.callbackHandles) {
        handle->bufferReleaseChannel = mBufferReleaseChannel;
        handle->transformHint = mTransformHint;
        handle->dequeueReadyTime = dequeueReadyTime;
        handle->currentMaxAcquiredBufferCount =
@@ -3518,11 +3508,6 @@ bool Layer::setTrustedPresentationInfo(TrustedPresentationThresholds const& thre
    return haveTrustedPresentationListener;
}

void Layer::setBufferReleaseChannel(
        const std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint>& channel) {
    mBufferReleaseChannel = channel;
}

void Layer::updateLastLatchTime(nsecs_t latchTime) {
    mLastLatchTime = latchTime;
}
+0 −3
Original line number Diff line number Diff line
@@ -537,7 +537,6 @@ public:
    };

    BufferInfo mBufferInfo;
    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseChannel;

    // implements compositionengine::LayerFE
    const compositionengine::LayerFECompositionState* getCompositionState() const;
@@ -725,8 +724,6 @@ public:

    bool setTrustedPresentationInfo(TrustedPresentationThresholds const& thresholds,
                                    TrustedPresentationListener const& listener);
    void setBufferReleaseChannel(
            const std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint>& channel);

    // Creates a new handle each time, so we only expect
    // this to be called once.
+0 −4
Original line number Diff line number Diff line
@@ -5063,10 +5063,6 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f
        }
    }

    if (what & layer_state_t::eBufferReleaseChannelChanged) {
        layer->setBufferReleaseChannel(s.bufferReleaseChannel);
    }

    const auto& requestedLayerState = mLayerLifecycleManager.getLayerFromId(layer->getSequence());
    bool willPresentCurrentTransaction = requestedLayerState &&
            (requestedLayerState->hasReadyFrame() ||
Loading