Loading include/gui/ConsumerBase.h +43 −12 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <utils/threads.h> #include <gui/IConsumerListener.h> #include <queue> namespace android { // ---------------------------------------------------------------------------- Loading Loading @@ -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 Loading Loading @@ -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; }; // ---------------------------------------------------------------------------- Loading libs/gui/ConsumerBase.cpp +77 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading @@ -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; Loading @@ -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"); Loading @@ -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() { Loading libs/gui/tests/SurfaceTextureGLToGL_test.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -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()); Loading Loading
include/gui/ConsumerBase.h +43 −12 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ #include <utils/threads.h> #include <gui/IConsumerListener.h> #include <queue> namespace android { // ---------------------------------------------------------------------------- Loading Loading @@ -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 Loading Loading @@ -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; }; // ---------------------------------------------------------------------------- Loading
libs/gui/ConsumerBase.cpp +77 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading @@ -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; Loading @@ -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"); Loading @@ -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() { Loading
libs/gui/tests/SurfaceTextureGLToGL_test.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -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()); Loading