From b4373ac9f53e3a6edee915715101d535e1a851a1 Mon Sep 17 00:00:00 2001 From: Aravind Akella Date: Wed, 29 Oct 2014 17:55:20 -0700 Subject: [PATCH 1/2] Add a timeout for releasing SensorService wake_lock. If SensorService is holding a wake_lock and there are no acknowledgements from ANY app within 5 seconds, release the wake_lock and reset the wake_lock refcounts for all connections. Bug: 16874240 Change-Id: I5e950dd393c20173c439cbd5a4ba614ee09d61f4 --- services/sensorservice/SensorService.cpp | 111 +++++++++++++++++------ services/sensorservice/SensorService.h | 21 ++++- 2 files changed, 102 insertions(+), 30 deletions(-) diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index dc8fa649d..c316ef6eb 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -191,6 +191,8 @@ void SensorService::onFirstRef() mSensorEventScratch = new sensors_event_t[minBufferSize]; mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize]; + mAckReceiver = new SensorEventAckReceiver(this); + mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; run("SensorService", PRIORITY_URGENT_DISPLAY); } @@ -386,8 +388,6 @@ bool SensorService::threadLoop() SensorDevice& device(SensorDevice::getInstance()); const size_t vcount = mVirtualSensorList.size(); - SensorEventAckReceiver sender(this); - sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); const int halVersion = device.getHalDeviceVersion(); do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax); @@ -408,16 +408,7 @@ bool SensorService::threadLoop() // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for // cleanup. So copy all the strongPointers to a vector before the lock is acquired. SortedVector< sp > activeConnections; - { - Mutex::Autolock _l(mLock); - for (size_t i=0 ; i < mActiveConnections.size(); ++i) { - sp connection(mActiveConnections[i].promote()); - if (connection != 0) { - activeConnections.add(connection); - } - } - } - + populateActiveConnections(&activeConnections); Mutex::Autolock _l(mLock); // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock, @@ -433,8 +424,7 @@ bool SensorService::threadLoop() } if (bufferHasWakeUpEvent && !mWakeLockAcquired) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - mWakeLockAcquired = true; + setWakeLockAcquiredLocked(true); } recordLastValueLocked(mSensorEventBuffer, count); @@ -522,8 +512,7 @@ bool SensorService::threadLoop() } if (mWakeLockAcquired && !needsWakeLock) { - release_wake_lock(WAKE_LOCK_NAME); - mWakeLockAcquired = false; + setWakeLockAcquiredLocked(false); } } while (!Thread::exitPending()); @@ -536,11 +525,52 @@ sp SensorService::getLooper() const { return mLooper; } +void SensorService::resetAllWakeLockRefCounts() { + SortedVector< sp > activeConnections; + populateActiveConnections(&activeConnections); + { + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i < activeConnections.size(); ++i) { + if (activeConnections[i] != 0) { + activeConnections[i]->resetWakeLockRefCount(); + } + } + setWakeLockAcquiredLocked(false); + } +} + +void SensorService::setWakeLockAcquiredLocked(bool acquire) { + if (acquire) { + if (!mWakeLockAcquired) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); + mWakeLockAcquired = true; + } + mLooper->wake(); + } else { + if (mWakeLockAcquired) { + release_wake_lock(WAKE_LOCK_NAME); + mWakeLockAcquired = false; + } + } +} + + +bool SensorService::isWakeLockAcquired() { + Mutex::Autolock _l(mLock); + return mWakeLockAcquired; +} + bool SensorService::SensorEventAckReceiver::threadLoop() { ALOGD("new thread SensorEventAckReceiver"); + sp looper = mService->getLooper(); do { - sp looper = mService->getLooper(); - looper->pollOnce(-1); + bool wakeLockAcquired = mService->isWakeLockAcquired(); + int timeout = -1; + if (wakeLockAcquired) timeout = 5000; + int ret = looper->pollOnce(timeout); + if (ret == ALOOPER_POLL_TIMEOUT) { + mService->resetAllWakeLockRefCounts(); + } } while(!Thread::exitPending()); return false; } @@ -714,10 +744,7 @@ status_t SensorService::enable(const sp& connection, sensors_event_t& event(mLastEventSeen.editValueFor(handle)); if (event.version == sizeof(sensors_event_t)) { if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - mWakeLockAcquired = true; - ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock for on_change sensor %s", - WAKE_LOCK_NAME); + setWakeLockAcquiredLocked(true); } connection->sendEvents(&event, 1, NULL); if (!connection->needsWakeLock() && mWakeLockAcquired) { @@ -922,8 +949,26 @@ void SensorService::checkWakeLockStateLocked() { } } if (releaseLock) { - release_wake_lock(WAKE_LOCK_NAME); - mWakeLockAcquired = false; + setWakeLockAcquiredLocked(false); + } +} + +void SensorService::sendEventsFromCache(const sp& connection) { + Mutex::Autolock _l(mLock); + connection->writeToSocketFromCache(); + if (connection->needsWakeLock()) { + setWakeLockAcquiredLocked(true); + } +} + +void SensorService::populateActiveConnections( + SortedVector< sp >* activeConnections) { + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i < mActiveConnections.size(); ++i) { + sp connection(mActiveConnections[i].promote()); + if (connection != 0) { + activeConnections->add(connection); + } } } @@ -1013,6 +1058,11 @@ bool SensorService::SensorEventConnection::needsWakeLock() { return !mDead && mWakeLockRefCount > 0; } +void SensorService::SensorEventConnection::resetWakeLockRefCount() { + Mutex::Autolock _l(mConnectionLock); + mWakeLockRefCount = 0; +} + void SensorService::SensorEventConnection::dump(String8& result) { Mutex::Autolock _l(mConnectionLock); result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n", @@ -1334,11 +1384,14 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { while (flushInfo.mPendingFlushEventsToSend > 0) { const int sensor_handle = mSensorInfo.keyAt(i); flushCompleteEvent.meta_data.sensor = sensor_handle; - if (mService->getSensorFromHandle(sensor_handle).isWakeUpSensor()) { + bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor(); + if (wakeUpSensor) { + ++mWakeLockRefCount; flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; } ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1); if (size < 0) { + if (wakeUpSensor) --mWakeLockRefCount; return; } ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ", @@ -1348,11 +1401,12 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { } } -void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() { +void SensorService::SensorEventConnection::writeToSocketFromCache() { // At a time write at most half the size of the receiver buffer in SensorEventQueue OR // half the size of the socket buffer allocated in BitTube whichever is smaller. const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2, int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2))); + Mutex::Autolock _l(mConnectionLock); // Send pending flush complete events (if any) sendPendingFlushEventsLocked(); for (int numEventsSent = 0; numEventsSent < mCacheSize;) { @@ -1503,9 +1557,8 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* } if (events & ALOOPER_EVENT_OUTPUT) { - // send sensor data that is stored in mEventCache. - Mutex::Autolock _l(mConnectionLock); - writeToSocketFromCacheLocked(); + // send sensor data that is stored in mEventCache for this connection. + mService->sendEventsFromCache(this); } return 1; } diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 5e3eeb59f..8719487e2 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -101,7 +101,7 @@ class SensorService : void sendPendingFlushEventsLocked(); // Writes events from mEventCache to the socket. - void writeToSocketFromCacheLocked(); + void writeToSocketFromCache(); // Compute the approximate cache size from the FIFO sizes of various sensors registered for // this connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be @@ -182,6 +182,7 @@ class SensorService : void setFirstFlushPending(int32_t handle, bool value); void dump(String8& result); bool needsWakeLock(); + void resetWakeLockRefCount(); uid_t getUid() const { return mUid; } }; @@ -230,12 +231,29 @@ class SensorService : // corresponding applications, if yes the wakelock is released. void checkWakeLockState(); void checkWakeLockStateLocked(); + bool isWakeLockAcquired(); bool isWakeUpSensorEvent(const sensors_event_t& event) const; SensorRecord * getSensorRecord(int handle); sp getLooper() const; + // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if + // SensorService did not receive any acknowledgements from apps which have registered for + // wake_up sensors. + void resetAllWakeLockRefCounts(); + + // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to + // 5 seconds and wake the looper. + void setWakeLockAcquiredLocked(bool acquire); + + // Send events from the event cache for this particular connection. + void sendEventsFromCache(const sp& connection); + + // Promote all weak referecences in mActiveConnections vector to strong references and add them + // to the output vector. + void populateActiveConnections(SortedVector< sp >* activeConnections); + // constants Vector mSensorList; Vector mUserSensorListDebug; @@ -247,6 +265,7 @@ class SensorService : // supported or not. uint32_t mSocketBufferSize; sp mLooper; + sp mAckReceiver; // protected by mLock mutable Mutex mLock; From 8dc55396fc9bc425b5e2c82e76a38080f2a655ff Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Tue, 4 Nov 2014 11:37:46 -0800 Subject: [PATCH 2/2] Add a BufferItem parameter to onFrameAvailable Passes the BufferItem for the queued buffer to the onFrameAvailable callback so the consumer can track the BufferQueue's contents. Also adds an onFrameReplaced callback, which is necessary if the consumer wants to do anything more than simple queue length tracking. Bug: 18111837 Change-Id: If9d07229c9b586c668e5f99074e9b63b0468feb0 --- include/gui/BufferItem.h | 1 + include/gui/BufferQueue.h | 2 +- include/gui/BufferQueueProducer.h | 10 +++++ include/gui/ConsumerBase.h | 4 +- include/gui/IConsumerListener.h | 19 +++++++- include/gui/StreamSplitter.h | 2 +- libs/gui/BufferItem.cpp | 2 + libs/gui/BufferQueue.cpp | 5 ++- libs/gui/BufferQueueProducer.cpp | 44 +++++++++++++++---- libs/gui/ConsumerBase.cpp | 4 +- libs/gui/IConsumerListener.cpp | 20 +++++---- libs/gui/StreamSplitter.cpp | 2 +- libs/gui/tests/BufferQueue_test.cpp | 2 +- libs/gui/tests/DisconnectWaiter.h | 2 +- libs/gui/tests/FrameWaiter.h | 2 +- .../gui/tests/IGraphicBufferProducer_test.cpp | 2 +- libs/gui/tests/StreamSplitter_test.cpp | 2 +- libs/gui/tests/SurfaceTextureGLThreadToGL.h | 2 +- opengl/tests/EGLTest/EGL_test.cpp | 2 +- .../DisplayHardware/FramebufferSurface.cpp | 2 +- .../DisplayHardware/FramebufferSurface.h | 2 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 2 +- 23 files changed, 99 insertions(+), 38 deletions(-) diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h index 5effd10e0..01b6ff4b5 100644 --- a/include/gui/BufferItem.h +++ b/include/gui/BufferItem.h @@ -44,6 +44,7 @@ class BufferItem : public Flattenable { // The default value of mBuf, used to indicate this doesn't correspond to a slot. enum { INVALID_BUFFER_SLOT = -1 }; BufferItem(); + ~BufferItem(); operator IGraphicBufferConsumer::BufferItem() const; static const char* scalingModeName(uint32_t scalingMode); diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index 3297b1044..118883745 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -62,7 +62,7 @@ public: public: ProxyConsumerListener(const wp& consumerListener); virtual ~ProxyConsumerListener(); - virtual void onFrameAvailable(); + virtual void onFrameAvailable(const android::BufferItem& item); virtual void onBuffersReleased(); virtual void onSidebandStreamChanged(); private: diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index c619a111c..ed1056a59 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -203,6 +203,16 @@ private: // since the previous buffer might have already been acquired. sp mLastQueueBufferFence; + // Take-a-ticket system for ensuring that onFrame* callbacks are called in + // the order that frames are queued. While the BufferQueue lock + // (mCore->mMutex) is held, a ticket is retained by the producer. After + // dropping the BufferQueue lock, the producer must wait on the condition + // variable until the current callback ticket matches its retained ticket. + Mutex mCallbackMutex; + int mNextCallbackTicket; // Protected by mCore->mMutex + int mCurrentCallbackTicket; // Protected by mCallbackMutex + Condition mCallbackCondition; + }; // class BufferQueueProducer } // namespace android diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h index 100bb260f..f7ab5ac59 100644 --- a/include/gui/ConsumerBase.h +++ b/include/gui/ConsumerBase.h @@ -46,7 +46,7 @@ public: // // This is called without any lock held and can be called concurrently // by multiple threads. - virtual void onFrameAvailable() = 0; + virtual void onFrameAvailable(const BufferItem& item) = 0; }; virtual ~ConsumerBase(); @@ -106,7 +106,7 @@ protected: // 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(); + virtual void onFrameAvailable(const BufferItem& item); virtual void onBuffersReleased(); virtual void onSidebandStreamChanged(); diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h index 260099e8d..2ef7c4dc1 100644 --- a/include/gui/IConsumerListener.h +++ b/include/gui/IConsumerListener.h @@ -28,6 +28,8 @@ namespace android { // ---------------------------------------------------------------------------- +class BufferItem; + // ConsumerListener is the interface through which the BufferQueue notifies // the consumer of events that the consumer may wish to react to. Because // the consumer will generally have a mutex that is locked during calls from @@ -43,11 +45,24 @@ public: // frame becomes available for consumption. This means that frames that // are queued while in asynchronous mode only trigger the callback if no // previous frames are pending. Frames queued while in synchronous mode - // always trigger the callback. + // always trigger the callback. The item passed to the callback will contain + // all of the information about the queued frame except for its + // GraphicBuffer pointer, which will always be null. // // This is called without any lock held and can be called concurrently // by multiple threads. - virtual void onFrameAvailable() = 0; /* Asynchronous */ + virtual void onFrameAvailable(const BufferItem& item) = 0; /* Asynchronous */ + + // onFrameReplaced is called from queueBuffer if the frame being queued is + // replacing an existing slot in the queue. Any call to queueBuffer that + // doesn't call onFrameAvailable will call this callback instead. The item + // passed to the callback will contain all of the information about the + // queued frame except for its GraphicBuffer pointer, which will always be + // null. + // + // This is called without any lock held and can be called concurrently + // by multiple threads. + virtual void onFrameReplaced(const BufferItem& item) {} /* Asynchronous */ // onBuffersReleased is called to notify the buffer consumer that the // BufferQueue has released its references to one or more GraphicBuffers diff --git a/include/gui/StreamSplitter.h b/include/gui/StreamSplitter.h index f9279539a..8f47eb47a 100644 --- a/include/gui/StreamSplitter.h +++ b/include/gui/StreamSplitter.h @@ -74,7 +74,7 @@ private: // can block if there are too many outstanding buffers. If it blocks, it // will resume when onBufferReleasedByOutput releases a buffer back to the // input. - virtual void onFrameAvailable(); + virtual void onFrameAvailable(const BufferItem& item); // From IConsumerListener // We don't care about released buffers because we detach each buffer as diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index d3fa43e75..e6fc79119 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -36,6 +36,8 @@ BufferItem::BufferItem() : mCrop.makeInvalid(); } +BufferItem::~BufferItem() {} + BufferItem::operator IGraphicBufferConsumer::BufferItem() const { IGraphicBufferConsumer::BufferItem bufferItem; bufferItem.mGraphicBuffer = mGraphicBuffer; diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index c49a8868f..61fd8c42d 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -31,10 +31,11 @@ BufferQueue::ProxyConsumerListener::ProxyConsumerListener( BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} -void BufferQueue::ProxyConsumerListener::onFrameAvailable() { +void BufferQueue::ProxyConsumerListener::onFrameAvailable( + const android::BufferItem& item) { sp listener(mConsumerListener.promote()); if (listener != NULL) { - listener->onFrameAvailable(); + listener->onFrameAvailable(item); } } diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 284ddb2bf..4d3b008df 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -39,7 +39,11 @@ BufferQueueProducer::BufferQueueProducer(const sp& core) : mSlots(core->mSlots), mConsumerName(), mStickyTransform(0), - mLastQueueBufferFence(Fence::NO_FENCE) {} + mLastQueueBufferFence(Fence::NO_FENCE), + mCallbackMutex(), + mNextCallbackTicket(0), + mCurrentCallbackTicket(0), + mCallbackCondition() {} BufferQueueProducer::~BufferQueueProducer() {} @@ -542,7 +546,10 @@ status_t BufferQueueProducer::queueBuffer(int slot, return BAD_VALUE; } - sp listener; + sp frameAvailableListener; + sp frameReplacedListener; + int callbackTicket = 0; + BufferItem item; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); @@ -598,7 +605,6 @@ status_t BufferQueueProducer::queueBuffer(int slot, ++mCore->mFrameCounter; mSlots[slot].mFrameNumber = mCore->mFrameCounter; - BufferItem item; item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; item.mCrop = crop; @@ -619,7 +625,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; + frameAvailableListener = mCore->mConsumerListener; } else { // When the queue is not empty, we need to look at the front buffer // state to see if we need to replace it @@ -635,9 +641,10 @@ status_t BufferQueueProducer::queueBuffer(int slot, } // Overwrite the droppable buffer with the incoming one *front = item; + frameReplacedListener = mCore->mConsumerListener; } else { mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; + frameAvailableListener = mCore->mConsumerListener; } } @@ -648,6 +655,9 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mTransformHint, mCore->mQueue.size()); ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); + + // Take a ticket for the callback functions + callbackTicket = mNextCallbackTicket++; } // Autolock scope // Wait without lock held @@ -659,9 +669,27 @@ status_t BufferQueueProducer::queueBuffer(int slot, mLastQueueBufferFence = fence; } - // Call back without lock held - if (listener != NULL) { - listener->onFrameAvailable(); + // Don't send the GraphicBuffer through the callback, and don't send + // the slot number, since the consumer shouldn't need it + item.mGraphicBuffer.clear(); + item.mSlot = BufferItem::INVALID_BUFFER_SLOT; + + // Call back without the main BufferQueue lock held, but with the callback + // lock held so we can ensure that callbacks occur in order + { + Mutex::Autolock lock(mCallbackMutex); + while (callbackTicket != mCurrentCallbackTicket) { + mCallbackCondition.wait(mCallbackMutex); + } + + if (frameAvailableListener != NULL) { + frameAvailableListener->onFrameAvailable(item); + } else if (frameReplacedListener != NULL) { + frameReplacedListener->onFrameReplaced(item); + } + + ++mCurrentCallbackTicket; + mCallbackCondition.broadcast(); } return NO_ERROR; diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index f19b6c773..210e98e44 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -98,7 +98,7 @@ void ConsumerBase::freeBufferLocked(int slotIndex) { mSlots[slotIndex].mFrameNumber = 0; } -void ConsumerBase::onFrameAvailable() { +void ConsumerBase::onFrameAvailable(const BufferItem& item) { CB_LOGV("onFrameAvailable"); sp listener; @@ -109,7 +109,7 @@ void ConsumerBase::onFrameAvailable() { if (listener != NULL) { CB_LOGV("actually calling onFrameAvailable"); - listener->onFrameAvailable(); + listener->onFrameAvailable(item); } } diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp index 4ccf0ac82..409dfe4ee 100644 --- a/libs/gui/IConsumerListener.cpp +++ b/libs/gui/IConsumerListener.cpp @@ -21,6 +21,7 @@ #include #include +#include // --------------------------------------------------------------------------- namespace android { @@ -39,9 +40,10 @@ public: : BpInterface(impl) { } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& item) { Parcel data, reply; data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); + data.write(item); remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); } @@ -66,18 +68,20 @@ status_t BnConsumerListener::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { - case ON_FRAME_AVAILABLE: + case ON_FRAME_AVAILABLE: { CHECK_INTERFACE(IConsumerListener, data, reply); - onFrameAvailable(); - return NO_ERROR; - case ON_BUFFER_RELEASED: + BufferItem item; + data.read(item); + onFrameAvailable(item); + return NO_ERROR; } + case ON_BUFFER_RELEASED: { CHECK_INTERFACE(IConsumerListener, data, reply); onBuffersReleased(); - return NO_ERROR; - case ON_SIDEBAND_STREAM_CHANGED: + return NO_ERROR; } + case ON_SIDEBAND_STREAM_CHANGED: { CHECK_INTERFACE(IConsumerListener, data, reply); onSidebandStreamChanged(); - return NO_ERROR; + return NO_ERROR; } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp index 771b263e7..5f39905e5 100644 --- a/libs/gui/StreamSplitter.cpp +++ b/libs/gui/StreamSplitter.cpp @@ -98,7 +98,7 @@ void StreamSplitter::setName(const String8 &name) { mInput->setConsumerName(name); } -void StreamSplitter::onFrameAvailable() { +void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) { ATRACE_CALL(); Mutex::Autolock lock(mMutex); diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index c7813664e..96de11f20 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -67,7 +67,7 @@ protected: }; struct DummyConsumer : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/libs/gui/tests/DisconnectWaiter.h b/libs/gui/tests/DisconnectWaiter.h index 56e96c295..6e6915b29 100644 --- a/libs/gui/tests/DisconnectWaiter.h +++ b/libs/gui/tests/DisconnectWaiter.h @@ -44,7 +44,7 @@ public: mPendingFrames--; } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& /* item */) { Mutex::Autolock lock(mMutex); mPendingFrames++; mFrameCondition.signal(); diff --git a/libs/gui/tests/FrameWaiter.h b/libs/gui/tests/FrameWaiter.h index bdedba67a..f78fa001c 100644 --- a/libs/gui/tests/FrameWaiter.h +++ b/libs/gui/tests/FrameWaiter.h @@ -35,7 +35,7 @@ public: mPendingFrames--; } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& /* item */) { Mutex::Autolock lock(mMutex); mPendingFrames++; mCondition.signal(); diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp index aadfe6177..8d5fd8f58 100644 --- a/libs/gui/tests/IGraphicBufferProducer_test.cpp +++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp @@ -65,7 +65,7 @@ const sp QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE; }; // namespace anonymous struct DummyConsumer : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp index 32ec90d55..4e63a6f4d 100644 --- a/libs/gui/tests/StreamSplitter_test.cpp +++ b/libs/gui/tests/StreamSplitter_test.cpp @@ -46,7 +46,7 @@ protected: }; struct DummyListener : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h index 6410516d2..14e42acfe 100644 --- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h +++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h @@ -130,7 +130,7 @@ protected: } // This should be called by GLConsumer on the producer thread. - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& /* item */) { Mutex::Autolock lock(mMutex); ALOGV("+onFrameAvailable"); mFrameAvailable = true; diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp index a4364c688..d69a27507 100644 --- a/opengl/tests/EGLTest/EGL_test.cpp +++ b/opengl/tests/EGLTest/EGL_test.cpp @@ -101,7 +101,7 @@ TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) { EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs)); struct DummyConsumer : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index b76798329..22d3cecbf 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -122,7 +122,7 @@ status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& } // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl. -void FramebufferSurface::onFrameAvailable() { +void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) { sp buf; sp acquireFence; status_t err = nextBuffer(buf, acquireFence); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index d0bf22be8..8605862e5 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -56,7 +56,7 @@ public: private: virtual ~FramebufferSurface() { }; // this class cannot be overloaded - virtual void onFrameAvailable(); + virtual void onFrameAvailable(const BufferItem& item); virtual void freeBufferLocked(int slotIndex); virtual void dumpLocked(String8& result, const char* prefix) const; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f6ad503b7..acc277531 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -159,7 +159,7 @@ void Layer::onLayerDisplayed(const sp& /* hw */, } } -void Layer::onFrameAvailable() { +void Layer::onFrameAvailable(const BufferItem& /* item */) { android_atomic_inc(&mQueuedFrames); mFlinger->signalLayerUpdate(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 1f8eff0c8..e2100fcd1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -330,7 +330,7 @@ protected: private: // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener - virtual void onFrameAvailable(); + virtual void onFrameAvailable(const BufferItem& item); virtual void onSidebandStreamChanged(); void commitTransaction();