summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/BufferQueueLayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/BufferQueueLayer.cpp')
-rw-r--r--services/surfaceflinger/BufferQueueLayer.cpp342
1 files changed, 189 insertions, 153 deletions
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 1de7afbf0c..6e4235e409 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -14,21 +14,24 @@
* limitations under the License.
*/
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
#undef LOG_TAG
#define LOG_TAG "BufferQueueLayer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <compositionengine/Display.h>
-#include <compositionengine/Layer.h>
-#include <compositionengine/OutputLayer.h>
-#include <compositionengine/impl/LayerCompositionState.h>
-#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include "BufferQueueLayer.h"
+
+#include <compositionengine/LayerFECompositionState.h>
#include <gui/BufferQueueConsumer.h>
#include <system/window.h>
-#include "BufferQueueLayer.h"
#include "LayerRejecter.h"
#include "SurfaceInterceptor.h"
+#include "FrameTracer/FrameTracer.h"
+#include "Scheduler/LayerHistory.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -36,6 +39,7 @@ namespace android {
BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
BufferQueueLayer::~BufferQueueLayer() {
+ mContentsChangedListener->abandon();
mConsumer->abandon();
}
@@ -45,26 +49,31 @@ BufferQueueLayer::~BufferQueueLayer() {
void BufferQueueLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
mConsumer->setReleaseFence(releaseFence);
+
+ // Prevent tracing the same release multiple times.
+ if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
+ mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+ std::make_shared<FenceTime>(releaseFence),
+ FrameTracer::FrameEvent::RELEASE_FENCE);
+ mPreviousReleasedFrameNumber = mPreviousFrameNumber;
+ }
}
-void BufferQueueLayer::setTransformHint(uint32_t orientation) const {
- mConsumer->setTransformHint(orientation);
+void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
+ BufferLayer::setTransformHint(displayTransformHint);
+ mConsumer->setTransformHint(mTransformHint);
}
std::vector<OccupancyTracker::Segment> BufferQueueLayer::getOccupancyHistory(bool forceFlush) {
std::vector<OccupancyTracker::Segment> history;
status_t result = mConsumer->getOccupancyHistory(forceFlush, &history);
if (result != NO_ERROR) {
- ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result);
+ ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result);
return {};
}
return history;
}
-bool BufferQueueLayer::getTransformToDisplayInverse() const {
- return mConsumer->getTransformToDisplayInverse();
-}
-
void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
if (!mConsumer->releasePendingBuffer()) {
return;
@@ -107,7 +116,11 @@ bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
ALOGW_IF(!isPlausible,
"[%s] Timestamp %" PRId64 " seems implausible "
"relative to expectedPresent %" PRId64,
- mName.string(), addedTime, expectedPresentTime);
+ getDebugName(), addedTime, expectedPresentTime);
+
+ if (!isPlausible) {
+ mFlinger->mTimeStats->incrementBadDesiredPresent(getSequence());
+ }
const bool isDue = addedTime < expectedPresentTime;
return isDue || !isPlausible;
@@ -134,71 +147,30 @@ bool BufferQueueLayer::fenceHasSignaled() const {
// able to be latched. To avoid this, grab this buffer anyway.
return true;
}
- return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+ const bool fenceSignaled =
+ mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+ if (!fenceSignaled) {
+ mFlinger->mTimeStats->incrementLatchSkipped(getSequence(),
+ TimeStats::LatchSkipReason::LateAcquire);
+ }
+
+ return fenceSignaled;
}
-bool BufferQueueLayer::framePresentTimeIsCurrent() const {
+bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
return true;
}
Mutex::Autolock lock(mQueueItemLock);
- return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
-}
-
-nsecs_t BufferQueueLayer::getDesiredPresentTime() {
- return mConsumer->getTimestamp();
-}
-
-std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTime() const {
- return mConsumer->getCurrentFenceTime();
-}
-
-void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) {
- return mConsumer->getTransformMatrix(matrix);
-}
-
-// NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's
-// These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state
-// so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's
-// current buffer so the consumer functions start with "getCurrent".
-//
-// This results in the rather confusing functions below.
-uint32_t BufferQueueLayer::getDrawingTransform() const {
- return mConsumer->getCurrentTransform();
-}
-
-ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const {
- return mConsumer->getCurrentDataSpace();
-}
-
-Rect BufferQueueLayer::getDrawingCrop() const {
- return mConsumer->getCurrentCrop();
-}
-
-uint32_t BufferQueueLayer::getDrawingScalingMode() const {
- return mConsumer->getCurrentScalingMode();
-}
-
-Region BufferQueueLayer::getDrawingSurfaceDamage() const {
- return mConsumer->getSurfaceDamage();
-}
-
-const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const {
- return mConsumer->getCurrentHdrMetadata();
-}
-
-int BufferQueueLayer::getDrawingApi() const {
- return mConsumer->getCurrentApi();
+ return mQueueItems[0].mTimestamp <= expectedPresentTime;
}
-uint64_t BufferQueueLayer::getFrameNumber() const {
+uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const {
Mutex::Autolock lock(mQueueItemLock);
uint64_t frameNumber = mQueueItems[0].mFrameNumber;
// The head of the queue will be dropped if there are signaled and timely frames behind it
- nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
-
if (isRemovedFromCurrentState()) {
expectedPresentTime = 0;
}
@@ -240,9 +212,9 @@ bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
// mSidebandStreamChanged was changed to false
mSidebandStream = mConsumer->getSidebandStream();
- auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
- layerCompositionState.sidebandStream = mSidebandStream;
- if (layerCompositionState.sidebandStream != nullptr) {
+ auto* layerCompositionState = editCompositionState();
+ layerCompositionState->sidebandStream = mSidebandStream;
+ if (layerCompositionState->sidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
@@ -257,26 +229,21 @@ bool BufferQueueLayer::hasFrameUpdate() const {
return mQueuedFrames > 0;
}
-void BufferQueueLayer::setFilteringEnabled(bool enabled) {
- return mConsumer->setFilteringEnabled(enabled);
-}
-
status_t BufferQueueLayer::bindTextureImage() {
return mConsumer->bindTextureImage();
}
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) {
// This boolean is used to make sure that SurfaceFlinger's shadow copy
// of the buffer queue isn't modified when the buffer queue is returning
// BufferItem's that weren't actually queued. This can happen in shared
// buffer mode.
bool queuedBuffer = false;
- const int32_t layerID = getSequence();
+ const int32_t layerId = getSequence();
LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
- getTransformToDisplayInverse(), mFreezeGeometryUpdates);
-
- nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
+ getProducerStickyTransform() != 0, mName, mOverrideScalingMode,
+ getTransformToDisplayInverse());
if (isRemovedFromCurrentState()) {
expectedPresentTime = 0;
@@ -314,7 +281,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t
if (queuedBuffer) {
Mutex::Autolock lock(mQueueItemLock);
mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
- mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber);
+ mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
mQueueItems.removeAt(0);
mQueuedFrames--;
}
@@ -328,7 +295,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t
Mutex::Autolock lock(mQueueItemLock);
mQueueItems.clear();
mQueuedFrames = 0;
- mFlinger->mTimeStats->onDestroy(layerID);
+ mFlinger->mTimeStats->onDestroy(layerId);
+ mFlinger->mFrameTracer->onDestroy(layerId);
}
// Once we have hit this state, the shadow queue may no longer
@@ -350,14 +318,15 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t
// updateTexImage
while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
- mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber);
+ mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
mQueueItems.removeAt(0);
mQueuedFrames--;
}
- mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber,
- mQueueItems[0].mFenceTime);
- mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime);
+ uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
+ mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
+ FrameTracer::FrameEvent::LATCH);
mQueueItems.removeAt(0);
}
@@ -373,12 +342,11 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t
status_t BufferQueueLayer::updateActiveBuffer() {
// update the active buffer
- mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence);
- auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
- layerCompositionState.buffer = mActiveBuffer;
- layerCompositionState.bufferSlot = mActiveBufferSlot;
+ mPreviousBufferId = getCurrentBufferId();
+ mBufferInfo.mBuffer =
+ mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);
- if (mActiveBuffer == nullptr) {
+ if (mBufferInfo.mBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
return BAD_VALUE;
}
@@ -396,55 +364,45 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) {
return NO_ERROR;
}
-void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
- const auto outputLayer = findOutputLayerForDisplay(display);
- LOG_FATAL_IF(!outputLayer);
- LOG_FATAL_IF(!outputLayer->getState.hwc);
- auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
-
- uint32_t hwcSlot = 0;
- sp<GraphicBuffer> hwcBuffer;
-
- // INVALID_BUFFER_SLOT is used to identify BufferStateLayers. Default to 0
- // for BufferQueueLayers
- int slot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot;
- (*outputLayer->editState().hwc)
- .hwcBufferCache.getHwcBuffer(slot, mActiveBuffer, &hwcSlot, &hwcBuffer);
-
- auto acquireFence = mConsumer->getCurrentFence();
- auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle,
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
- layerCompositionState.bufferSlot = mActiveBufferSlot;
- layerCompositionState.buffer = mActiveBuffer;
- layerCompositionState.acquireFence = acquireFence;
-}
-
// -----------------------------------------------------------------------
// Interface implementation for BufferLayerConsumer::ContentsChangedListener
// -----------------------------------------------------------------------
-void BufferQueueLayer::fakeVsync() {
- mRefreshPending = false;
- bool ignored = false;
- latchBuffer(ignored, systemTime());
- usleep(16000);
- releasePendingBuffer(systemTime());
+void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) {
+ const int32_t layerId = getSequence();
+ mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER,
+ systemTime(), FrameTracer::FrameEvent::DEQUEUE);
+}
+
+void BufferQueueLayer::onFrameDetached(const uint64_t bufferId) {
+ const int32_t layerId = getSequence();
+ mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER,
+ systemTime(), FrameTracer::FrameEvent::DETACH);
+}
+
+void BufferQueueLayer::onFrameCancelled(const uint64_t bufferId) {
+ const int32_t layerId = getSequence();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER,
+ systemTime(), FrameTracer::FrameEvent::CANCEL);
}
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
+ const int32_t layerId = getSequence();
+ const uint64_t bufferId = item.mGraphicBuffer->getId();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+ FrameTracer::FrameEvent::QUEUE);
+ mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+ std::make_shared<FenceTime>(item.mFence),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
+
ATRACE_CALL();
// Add this buffer from our internal queue tracker
{ // Autolock scope
- if (mFlinger->mUseSmart90ForVideo) {
- const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp;
- mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime,
- item.mHdrMetadata.validTypes != 0);
- }
+ const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp;
+ mFlinger->mScheduler->recordLayerHistory(this, presentTime,
+ LayerHistory::LayerUpdateType::Buffer);
Mutex::Autolock lock(mQueueItemLock);
// Reset the frame number tracker when we receive the first buffer after
@@ -457,7 +415,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
+ ALOGE("[%s] Timed out waiting on callback", getDebugName());
break;
}
}
@@ -470,16 +428,10 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
mQueueItemCondition.broadcast();
}
- mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
item.mGraphicBuffer->getHeight(), item.mFrameNumber);
- // If this layer is orphaned, then we run a fake vsync pulse so that
- // dequeueBuffer doesn't block indefinitely.
- if (isRemovedFromCurrentState()) {
- fakeVsync();
- } else {
- mFlinger->signalLayerUpdate();
- }
+ mFlinger->signalLayerUpdate();
mConsumer->onBufferAvailable(item);
}
@@ -492,7 +444,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
+ ALOGE("[%s] Timed out waiting on callback", getDebugName());
break;
}
}
@@ -507,6 +459,14 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
mLastFrameNumberReceived = item.mFrameNumber;
mQueueItemCondition.broadcast();
}
+
+ const int32_t layerId = getSequence();
+ const uint64_t bufferId = item.mGraphicBuffer->getId();
+ mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+ FrameTracer::FrameEvent::QUEUE);
+ mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+ std::make_shared<FenceTime>(item.mFence),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
mConsumer->onBufferAvailable(item);
}
@@ -526,26 +486,21 @@ void BufferQueueLayer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, true);
- mProducer = new MonitoredProducer(producer, mFlinger, this);
- {
- // Grab the SF state lock during this since it's the only safe way to access RenderEngine
- Mutex::Autolock lock(mFlinger->mStateLock);
- mConsumer =
- new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
- }
+ mFlinger->getFactory().createBufferQueue(&producer, &consumer, true);
+ mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this);
+ mConsumer =
+ mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(),
+ mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
- mConsumer->setContentsChangedListener(this);
- mConsumer->setName(mName);
+
+ mContentsChangedListener = new ContentsChangedListener(this);
+ mConsumer->setContentsChangedListener(mContentsChangedListener);
+ mConsumer->setName(String8(mName.data(), mName.size()));
// BufferQueueCore::mMaxDequeuedBufferCount is default to 1
if (!mFlinger->isLayerTripleBufferingDisabled()) {
mProducer->setMaxDequeuedBufferCount(2);
}
-
- if (const auto display = mFlinger->getDefaultDisplayDevice()) {
- updateTransformHint(display);
- }
}
status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) {
@@ -581,4 +536,85 @@ uint32_t BufferQueueLayer::getProducerStickyTransform() const {
return static_cast<uint32_t>(producerStickyTransform);
}
+void BufferQueueLayer::gatherBufferInfo() {
+ BufferLayer::gatherBufferInfo();
+
+ mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp();
+ mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime();
+ mBufferInfo.mFence = mConsumer->getCurrentFence();
+ mBufferInfo.mTransform = mConsumer->getCurrentTransform();
+ mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace());
+ mBufferInfo.mCrop = mConsumer->getCurrentCrop();
+ mBufferInfo.mScaleMode = mConsumer->getCurrentScalingMode();
+ mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage();
+ mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata();
+ mBufferInfo.mApi = mConsumer->getCurrentApi();
+ mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
+}
+
+sp<Layer> BufferQueueLayer::createClone() {
+ LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
+ args.textureName = mTextureName;
+ sp<BufferQueueLayer> layer = mFlinger->getFactory().createBufferQueueLayer(args);
+ layer->setInitialValuesForClone(this);
+
+ return layer;
+}
+
+// -----------------------------------------------------------------------
+// Interface implementation for BufferLayerConsumer::ContentsChangedListener
+// -----------------------------------------------------------------------
+
+void BufferQueueLayer::ContentsChangedListener::onFrameAvailable(const BufferItem& item) {
+ Mutex::Autolock lock(mMutex);
+ if (mBufferQueueLayer != nullptr) {
+ mBufferQueueLayer->onFrameAvailable(item);
+ }
+}
+
+void BufferQueueLayer::ContentsChangedListener::onFrameReplaced(const BufferItem& item) {
+ Mutex::Autolock lock(mMutex);
+ if (mBufferQueueLayer != nullptr) {
+ mBufferQueueLayer->onFrameReplaced(item);
+ }
+}
+
+void BufferQueueLayer::ContentsChangedListener::onSidebandStreamChanged() {
+ Mutex::Autolock lock(mMutex);
+ if (mBufferQueueLayer != nullptr) {
+ mBufferQueueLayer->onSidebandStreamChanged();
+ }
+}
+
+void BufferQueueLayer::ContentsChangedListener::onFrameDequeued(const uint64_t bufferId) {
+ Mutex::Autolock lock(mMutex);
+ if (mBufferQueueLayer != nullptr) {
+ mBufferQueueLayer->onFrameDequeued(bufferId);
+ }
+}
+
+void BufferQueueLayer::ContentsChangedListener::onFrameDetached(const uint64_t bufferId) {
+ Mutex::Autolock lock(mMutex);
+ if (mBufferQueueLayer != nullptr) {
+ mBufferQueueLayer->onFrameDetached(bufferId);
+ }
+}
+
+void BufferQueueLayer::ContentsChangedListener::onFrameCancelled(const uint64_t bufferId) {
+ Mutex::Autolock lock(mMutex);
+ if (mBufferQueueLayer != nullptr) {
+ mBufferQueueLayer->onFrameCancelled(bufferId);
+ }
+}
+
+void BufferQueueLayer::ContentsChangedListener::abandon() {
+ Mutex::Autolock lock(mMutex);
+ mBufferQueueLayer = nullptr;
+}
+
+// -----------------------------------------------------------------------
+
} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"