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

Commit d880e517 authored by Pablo Ceballos's avatar Pablo Ceballos Committed by Android (Google) Code Review
Browse files

Merge "Add a callback thread to ConsumerBase" into nyc-dev

parents 085e02ec 22b5702b
Loading
Loading
Loading
Loading
+43 −12
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#include <utils/threads.h>
#include <gui/IConsumerListener.h>

#include <queue>

namespace android {
// ----------------------------------------------------------------------------

@@ -108,18 +110,18 @@ protected:
    // from the derived class.
    virtual void onLastStrongRef(const void* id);

    // Implementation of the IConsumerListener interface.  These
    // calls are used to notify the ConsumerBase of asynchronous events in the
    // BufferQueue.  The onFrameAvailable, onFrameReplaced, and
    // onBuffersReleased methods should not need to be overridden by derived
    // classes, but if they are overridden the ConsumerBase implementation must
    // be called from the derived class. The ConsumerBase version of
    // onSidebandStreamChanged does nothing and can be overriden by derived
    // classes if they want the notification.
    virtual void onFrameAvailable(const BufferItem& item) override;
    virtual void onFrameReplaced(const BufferItem& item) override;
    virtual void onBuffersReleased() override;
    virtual void onSidebandStreamChanged() override;
    // Handlers for the IConsumerListener interface, these will be called from
    // the message queue thread. These calls are used to notify the ConsumerBase
    // of asynchronous events in the BufferQueue.  The onFrameAvailableHandler,
    // onFrameReplacedHandler, and onBuffersReleasedHandler methods should not
    // need to be overridden by derived classes, but if they are overridden the
    // ConsumerBase implementation must be called from the derived class. The
    // ConsumerBase version of onSidebandStreamChangedHandler does nothing and
    // can be overriden by derived classes if they want the notification.
    virtual void onFrameAvailableHandler(const BufferItem& item);
    virtual void onFrameReplacedHandler(const BufferItem& item);
    virtual void onBuffersReleasedHandler();
    virtual void onSidebandStreamChangedHandler();

    // freeBufferLocked frees up the given buffer slot.  If the slot has been
    // initialized this will release the reference to the GraphicBuffer in that
@@ -244,6 +246,35 @@ protected:
    //
    // This mutex is intended to be locked by derived classes.
    mutable Mutex mMutex;

    // Implements the ConsumerListener interface
    virtual void onFrameAvailable(const BufferItem& item) override;
    virtual void onFrameReplaced(const BufferItem& item) override;
    virtual void onBuffersReleased() override;
    virtual void onSidebandStreamChanged() override;

    enum MessageType {
        ON_FRAME_AVAILABLE,
        ON_FRAME_REPLACED,
        ON_BUFFERS_RELEASED,
        ON_SIDEBAND_STREAM_CHANGED,
        EXIT,
    };

    mutable Mutex mMessageQueueLock;
    Condition mMessageAvailable;
    std::queue<std::pair<MessageType, BufferItem>> mMessageQueue;

    class MessageThread : public Thread {
    public:
        MessageThread(ConsumerBase* consumerBase) :
            mConsumerBase(consumerBase) {};
    protected:
        virtual bool threadLoop() override;
        ConsumerBase* mConsumerBase;
    };

    sp<MessageThread> mMessageThread;
};

// ----------------------------------------------------------------------------
+77 −1
Original line number Diff line number Diff line
@@ -74,12 +74,26 @@ ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool c
    } else {
        mConsumer->setConsumerName(mName);
    }

    mMessageThread = new MessageThread(this);
    mMessageThread->run();
}

ConsumerBase::~ConsumerBase() {
    CB_LOGV("~ConsumerBase");
    Mutex::Autolock lock(mMutex);

    mMessageThread->requestExit();
    {
        Mutex::Autolock lock(mMessageQueueLock);
        mMessageQueue.emplace(std::piecewise_construct,
                std::forward_as_tuple(EXIT),
                std::forward_as_tuple());
        mMessageAvailable.signal();
    }

    mMessageThread->join();

    Mutex::Autolock lock(mMutex);
    // Verify that abandon() has been called before we get here.  This should
    // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
    // derived class to override that method and not call
@@ -100,6 +114,13 @@ void ConsumerBase::freeBufferLocked(int slotIndex) {
}

void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    Mutex::Autolock lock(mMessageQueueLock);
    mMessageQueue.emplace(std::piecewise_construct,
            std::forward_as_tuple(ON_FRAME_AVAILABLE),
            std::forward_as_tuple(item));
    mMessageAvailable.signal();
}
void ConsumerBase::onFrameAvailableHandler(const BufferItem& item) {
    CB_LOGV("onFrameAvailable");

    sp<FrameAvailableListener> listener;
@@ -115,6 +136,14 @@ void ConsumerBase::onFrameAvailable(const BufferItem& item) {
}

void ConsumerBase::onFrameReplaced(const BufferItem &item) {
    Mutex::Autolock lock(mMessageQueueLock);
    mMessageQueue.emplace(std::piecewise_construct,
            std::forward_as_tuple(ON_FRAME_REPLACED),
            std::forward_as_tuple(item));
    mMessageAvailable.signal();
}

void ConsumerBase::onFrameReplacedHandler(const BufferItem &item) {
    CB_LOGV("onFrameReplaced");

    sp<FrameAvailableListener> listener;
@@ -130,6 +159,14 @@ void ConsumerBase::onFrameReplaced(const BufferItem &item) {
}

void ConsumerBase::onBuffersReleased() {
    Mutex::Autolock lock(mMessageQueueLock);
    mMessageQueue.emplace(std::piecewise_construct,
            std::forward_as_tuple(ON_BUFFERS_RELEASED),
            std::forward_as_tuple());
    mMessageAvailable.signal();
}

void ConsumerBase::onBuffersReleasedHandler() {
    Mutex::Autolock lock(mMutex);

    CB_LOGV("onBuffersReleased");
@@ -149,6 +186,45 @@ void ConsumerBase::onBuffersReleased() {
}

void ConsumerBase::onSidebandStreamChanged() {
    Mutex::Autolock lock(mMessageQueueLock);
    mMessageQueue.emplace(std::piecewise_construct,
            std::forward_as_tuple(ON_SIDEBAND_STREAM_CHANGED),
            std::forward_as_tuple());
    mMessageAvailable.signal();
}

void ConsumerBase::onSidebandStreamChangedHandler() {
}

bool ConsumerBase::MessageThread::threadLoop() {
    Mutex::Autolock lock(mConsumerBase->mMessageQueueLock);

    if (mConsumerBase->mMessageQueue.empty()) {
        mConsumerBase->mMessageAvailable.wait(mConsumerBase->mMessageQueueLock);
    }

    while (!mConsumerBase->mMessageQueue.empty()) {
        auto nextMessage = mConsumerBase->mMessageQueue.front();

        switch (nextMessage.first) {
            case ON_FRAME_AVAILABLE:
                mConsumerBase->onFrameAvailableHandler(nextMessage.second);
                break;
            case ON_FRAME_REPLACED:
                mConsumerBase->onFrameReplacedHandler(nextMessage.second);
                break;
            case ON_BUFFERS_RELEASED:
                mConsumerBase->onBuffersReleasedHandler();
                break;
            case ON_SIDEBAND_STREAM_CHANGED:
                mConsumerBase->onSidebandStreamChangedHandler();
                break;
            case EXIT:
                break;
        }
        mConsumerBase->mMessageQueue.pop();
    }
    return true;
}

void ConsumerBase::abandon() {
+4 −0
Original line number Diff line number Diff line
@@ -192,6 +192,10 @@ TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
    ASSERT_EQ(EGL_SUCCESS, eglGetError());
    mProducerEglSurface = EGL_NO_SURFACE;

    // sleep for 10ms to allow any asynchronous operations to complete before
    // checking the reference counts
    usleep(10000);

    // This test should have the only reference to buffer 0.
    EXPECT_EQ(1, buffers[0]->getStrongCount());