surfaceflinger: cache HWC client targets and buffers
Remember HWC client targets and buffers, and make sure we send each
unique slot/handle pair only once. This allows the composer to
clone/register/retain each buffer only once.
Test: builds and boots
Change-Id: Ib485189043a9c132031e82d4d7380ace3bf9453d
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 1bd9616..6cb1af1 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -20,6 +20,7 @@
#include <android/dvr/composer/1.0/IVrComposerClient.h>
#include <inttypes.h>
#include <log/log.h>
+#include <gui/BufferQueue.h>
#include "ComposerHal.h"
@@ -221,9 +222,8 @@
Error Composer::createLayer(Display display, Layer* outLayer)
{
- const uint32_t bufferSlotCount = 1;
Error error = kDefaultError;
- mClient->createLayer(display, bufferSlotCount,
+ mClient->createLayer(display, BufferQueue::NUM_BUFFER_SLOTS,
[&](const auto& tmpError, const auto& tmpLayer) {
error = tmpError;
if (error != Error::NONE) {
@@ -427,12 +427,13 @@
return unwrapRet(ret);
}
-Error Composer::setClientTarget(Display display, const native_handle_t* target,
+Error Composer::setClientTarget(Display display, uint32_t slot,
+ const native_handle_t* target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage)
{
mWriter.selectDisplay(display);
- mWriter.setClientTarget(0, target, acquireFence, dataspace, damage);
+ mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
return Error::NONE;
}
@@ -472,7 +473,7 @@
Error Composer::setClientTargetSlotCount(Display display)
{
- const uint32_t bufferSlotCount = 1;
+ const uint32_t bufferSlotCount = BufferQueue::NUM_BUFFER_SLOTS;
auto ret = mClient->setClientTargetSlotCount(display, bufferSlotCount);
return unwrapRet(ret);
}
@@ -503,11 +504,11 @@
}
Error Composer::setLayerBuffer(Display display, Layer layer,
- const native_handle_t* buffer, int acquireFence)
+ uint32_t slot, const native_handle_t* buffer, int acquireFence)
{
mWriter.selectDisplay(display);
mWriter.selectLayer(layer);
- mWriter.setLayerBuffer(0, buffer, acquireFence);
+ mWriter.setLayerBuffer(slot, buffer, acquireFence);
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 329d787..1ede705 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -172,7 +172,14 @@
Error presentDisplay(Display display, int* outPresentFence);
Error setActiveConfig(Display display, Config config);
- Error setClientTarget(Display display, const native_handle_t* target,
+
+ /*
+ * The composer caches client targets internally. When target is nullptr,
+ * the composer uses slot to look up the client target from its cache.
+ * When target is not nullptr, the cache is updated with the new target.
+ */
+ Error setClientTarget(Display display, uint32_t slot,
+ const native_handle_t* target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage);
Error setColorMode(Display display, ColorMode mode);
@@ -190,7 +197,8 @@
Error setCursorPosition(Display display, Layer layer,
int32_t x, int32_t y);
- Error setLayerBuffer(Display display, Layer layer,
+ /* see setClientTarget for the purpose of slot */
+ Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
const native_handle_t* buffer, int acquireFence);
Error setLayerSurfaceDamage(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& damage);
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index d801bb3..cb08f08 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -25,6 +25,7 @@
namespace android {
// ---------------------------------------------------------------------------
+class Fence;
class IGraphicBufferProducer;
class String8;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 1998edf..d3d0d51 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -100,16 +100,18 @@
status_t FramebufferSurface::advanceFrame() {
#ifdef USE_HWC2
+ uint32_t slot = 0;
sp<GraphicBuffer> buf;
sp<Fence> acquireFence(Fence::NO_FENCE);
android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
- status_t result = nextBuffer(buf, acquireFence, dataspace);
+ status_t result = nextBuffer(slot, buf, acquireFence, dataspace);
if (result != NO_ERROR) {
ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
strerror(-result), result);
return result;
}
- result = mHwc.setClientTarget(mDisplayType, acquireFence, buf, dataspace);
+ result = mHwc.setClientTarget(mDisplayType, slot,
+ acquireFence, buf, dataspace);
if (result != NO_ERROR) {
ALOGE("error posting framebuffer: %d", result);
}
@@ -123,8 +125,9 @@
}
#ifdef USE_HWC2
-status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer,
- sp<Fence>& outFence, android_dataspace_t& outDataspace) {
+status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
+ sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
+ android_dataspace_t& outDataspace) {
#else
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
#endif
@@ -133,7 +136,12 @@
BufferItem item;
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+#ifdef USE_HWC2
+ mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ &outSlot, &outBuffer);
+#else
outBuffer = mCurrentBuffer;
+#endif
return NO_ERROR;
} else if (err != NO_ERROR) {
ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
@@ -169,9 +177,12 @@
mCurrentFence = item.mFence;
outFence = item.mFence;
- outBuffer = mCurrentBuffer;
#ifdef USE_HWC2
+ mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ &outSlot, &outBuffer);
outDataspace = item.mDataSpace;
+#else
+ outBuffer = mCurrentBuffer;
#endif
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 439435a..5eea6b6 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -17,12 +17,14 @@
#ifndef ANDROID_SF_FRAMEBUFFER_SURFACE_H
#define ANDROID_SF_FRAMEBUFFER_SURFACE_H
+#include "DisplaySurface.h"
+
#include <stdint.h>
#include <sys/types.h>
#include <gui/ConsumerBase.h>
-#include "DisplaySurface.h"
+#include <memory>
// ---------------------------------------------------------------------------
namespace android {
@@ -31,6 +33,7 @@
class Rect;
class String8;
class HWComposer;
+class HWComposerBufferCache;
// ---------------------------------------------------------------------------
@@ -68,8 +71,8 @@
// BufferQueue and releases the previously latched buffer to the
// BufferQueue. The new buffer is returned in the 'buffer' argument.
#ifdef USE_HWC2
- status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
- android_dataspace_t& outDataspace);
+ status_t nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer,
+ sp<Fence>& outFence, android_dataspace_t& outDataspace);
#else
status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
#endif
@@ -93,6 +96,9 @@
HWComposer& mHwc;
#ifdef USE_HWC2
+ std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
+ std::make_unique<HWComposerBufferCache>();
+
// Previous buffer to release after getting an updated retire fence
bool mHasPendingRelease;
int mPreviousBufferSlot;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 6ff5ea1..99a6d71 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -962,17 +962,18 @@
return static_cast<Error>(intError);
}
-Error Display::setClientTarget(buffer_handle_t target,
+Error Display::setClientTarget(uint32_t slot, buffer_handle_t target,
const sp<Fence>& acquireFence, android_dataspace_t dataspace)
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
#ifdef BYPASS_IHWC
+ (void) slot;
int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
#else
- auto intError = mDevice.mComposer->setClientTarget(mId, target, fenceFd,
- static_cast<Hwc2::Dataspace>(dataspace),
+ auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
+ fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
std::vector<Hwc2::IComposerClient::Rect>());
#endif
return static_cast<Error>(intError);
@@ -1195,16 +1196,17 @@
return static_cast<Error>(intError);
}
-Error Layer::setBuffer(buffer_handle_t buffer,
+Error Layer::setBuffer(uint32_t slot, buffer_handle_t buffer,
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
#ifdef BYPASS_IHWC
+ (void) slot;
int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
mId, buffer, fenceFd);
#else
auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
- mId, buffer, fenceFd);
+ mId, slot, buffer, fenceFd);
#endif
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 256b05d..d770f22 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -322,7 +322,7 @@
[[clang::warn_unused_result]] Error setActiveConfig(
const std::shared_ptr<const Config>& config);
[[clang::warn_unused_result]] Error setClientTarget(
- buffer_handle_t target,
+ uint32_t slot, buffer_handle_t target,
const android::sp<android::Fence>& acquireFence,
android_dataspace_t dataspace);
[[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
@@ -384,7 +384,8 @@
hwc2_layer_t getId() const { return mId; }
[[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
- [[clang::warn_unused_result]] Error setBuffer(buffer_handle_t buffer,
+ [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
+ buffer_handle_t buffer,
const android::sp<android::Fence>& acquireFence);
[[clang::warn_unused_result]] Error setSurfaceDamage(
const android::Region& damage);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7914770..e86a071 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -444,7 +444,7 @@
}
}
-status_t HWComposer::setClientTarget(int32_t displayId,
+status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot,
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
android_dataspace_t dataspace) {
if (!isValidDisplay(displayId)) {
@@ -457,7 +457,8 @@
if ((target != nullptr) && target->getNativeBuffer()) {
handle = target->getNativeBuffer()->handle;
}
- auto error = hwcDisplay->setClientTarget(handle, acquireFence, dataspace);
+ auto error = hwcDisplay->setClientTarget(slot, handle,
+ acquireFence, dataspace);
if (error != HWC2::Error::None) {
ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
@@ -894,5 +895,36 @@
*this = DisplayData();
}
+void HWComposerBufferCache::clear()
+{
+ mBuffers.clear();
+}
+
+void HWComposerBufferCache::getHwcBuffer(int slot,
+ const sp<GraphicBuffer>& buffer,
+ uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
+{
+ if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
+ // default to slot 0
+ slot = 0;
+ }
+
+ if (static_cast<size_t>(slot) >= mBuffers.size()) {
+ mBuffers.resize(slot + 1);
+ }
+
+ *outSlot = slot;
+
+ if (mBuffers[slot] == buffer) {
+ // already cached in HWC, skip sending the buffer
+ *outBuffer = nullptr;
+ } else {
+ *outBuffer = buffer;
+
+ // update cache
+ mBuffers[slot] = buffer;
+ }
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 2713505..37f12e4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -26,6 +26,8 @@
#include <stdint.h>
#include <sys/types.h>
+#include <gui/BufferQueue.h>
+
#include <ui/Fence.h>
#include <utils/BitSet.h>
@@ -94,7 +96,8 @@
// Asks the HAL what it can do
status_t prepare(DisplayDevice& displayDevice);
- status_t setClientTarget(int32_t displayId, const sp<Fence>& acquireFence,
+ status_t setClientTarget(int32_t displayId, uint32_t slot,
+ const sp<Fence>& acquireFence,
const sp<GraphicBuffer>& target, android_dataspace_t dataspace);
// Present layers to the display and read releaseFences.
@@ -224,6 +227,19 @@
mutable Mutex mVsyncLock;
};
+class HWComposerBufferCache {
+public:
+ void clear();
+
+ void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer,
+ uint32_t* outSlot, sp<GraphicBuffer>* outBuffer);
+
+private:
+ // a vector as we expect "slot" to be in the range of [0, 63] (that is,
+ // less than BufferQueue::NUM_BUFFER_SLOTS).
+ std::vector<sp<GraphicBuffer>> mBuffers;
+};
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 6a98f03..5f3c388 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -221,9 +221,14 @@
status_t result = NO_ERROR;
if (fbBuffer != NULL) {
#ifdef USE_HWC2
+ uint32_t hwcSlot = 0;
+ sp<GraphicBuffer> hwcBuffer;
+ mHwcBufferCache->getHwcBuffer(mFbProducerSlot, fbBuffer,
+ &hwcSlot, &hwcBuffer);
+
// TODO: Correctly propagate the dataspace from GL composition
- result = mHwc.setClientTarget(mDisplayId, mFbFence, fbBuffer,
- HAL_DATASPACE_UNKNOWN);
+ result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence,
+ hwcBuffer, HAL_DATASPACE_UNKNOWN);
#else
result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
#endif
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index d37dc0a..2636667 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -17,16 +17,19 @@
#ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+#include "DisplaySurface.h"
+
#include <gui/ConsumerBase.h>
#include <gui/IGraphicBufferProducer.h>
-#include "DisplaySurface.h"
+#include <memory>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class HWComposer;
+class HWComposerBufferCache;
class IProducerListener;
/* This DisplaySurface implementation supports virtual displays, where GLES
@@ -250,6 +253,11 @@
static const char* dbgSourceStr(Source s);
bool mMustRecompose;
+
+#ifdef USE_HWC2
+ std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
+ std::make_unique<HWComposerBufferCache>();
+#endif
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e57c19a..3a9bca6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -270,6 +270,16 @@
}
}
+void Layer::onBuffersReleased() {
+#ifdef USE_HWC2
+ Mutex::Autolock lock(mHwcBufferCacheMutex);
+
+ for (auto info : mHwcBufferCaches) {
+ info.second.clear();
+ }
+#endif
+}
+
void Layer::onSidebandStreamChanged() {
if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
// mSidebandStreamChanged was false
@@ -836,8 +846,22 @@
static_cast<int32_t>(error));
}
+ uint32_t hwcSlot = 0;
+ buffer_handle_t hwcHandle = nullptr;
+ {
+ Mutex::Autolock lock(mHwcBufferCacheMutex);
+
+ auto& hwcBufferCache = mHwcBufferCaches[hwcId];
+ sp<GraphicBuffer> hwcBuffer;
+ hwcBufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+ &hwcSlot, &hwcBuffer);
+ if (hwcBuffer != nullptr) {
+ hwcHandle = hwcBuffer->handle;
+ }
+ }
+
auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
- error = hwcLayer->setBuffer(mActiveBuffer->handle, acquireFence);
+ error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
mActiveBuffer->handle, to_string(error).c_str(),
@@ -2087,7 +2111,8 @@
}
// update the active buffer
- mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
+ mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(
+ &mActiveBufferSlot);
if (mActiveBuffer == NULL) {
// this can only happen if the very first buffer was rejected.
return outDirtyRegion;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7335be7..76c710a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -376,13 +376,20 @@
#ifdef USE_HWC2
// -----------------------------------------------------------------------
+ void eraseHwcLayer(int32_t hwcId) {
+ mHwcLayers.erase(hwcId);
+
+ Mutex::Autolock lock(mHwcBufferCacheMutex);
+ mHwcBufferCaches.erase(hwcId);
+ }
+
bool hasHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
return false;
}
if (mHwcLayers[hwcId].layer->isAbandoned()) {
ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
- mHwcLayers.erase(hwcId);
+ eraseHwcLayer(hwcId);
return false;
}
return true;
@@ -398,8 +405,11 @@
void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
if (layer) {
mHwcLayers[hwcId].layer = layer;
+
+ Mutex::Autolock lock(mHwcBufferCacheMutex);
+ mHwcBufferCaches[hwcId] = HWComposerBufferCache();
} else {
- mHwcLayers.erase(hwcId);
+ eraseHwcLayer(hwcId);
}
}
@@ -489,6 +499,7 @@
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
virtual void onFrameAvailable(const BufferItem& item) override;
virtual void onFrameReplaced(const BufferItem& item) override;
+ virtual void onBuffersReleased() override;
virtual void onSidebandStreamChanged() override;
void commitTransaction(const State& stateToCommit);
@@ -642,6 +653,7 @@
FenceTimeline mReleaseTimeline;
// main thread
+ int mActiveBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
sp<GraphicBuffer> mActiveBuffer;
sp<NativeHandle> mSidebandStream;
Rect mCurrentCrop;
@@ -681,6 +693,12 @@
gfx::FloatRect sourceCrop;
};
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
+
+ // We need one HWComposerBufferCache for each HWC display. We cannot have
+ // HWComposerBufferCache in HWCInfo because HWCInfo can only be accessed
+ // from the main thread.
+ Mutex mHwcBufferCacheMutex;
+ std::unordered_map<int32_t, HWComposerBufferCache> mHwcBufferCaches;
#else
bool mIsGlesComposition;
#endif
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 029937a..942af13 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -235,6 +235,19 @@
mContentsChangedListener = listener;
}
+void SurfaceFlingerConsumer::onBuffersReleased() {
+ sp<ContentsChangedListener> listener;
+ { // scope for the lock
+ Mutex::Autolock lock(mMutex);
+ ALOG_ASSERT(mFrameAvailableListener.unsafe_get() == mContentsChangedListener.unsafe_get());
+ listener = mContentsChangedListener.promote();
+ }
+
+ if (listener != NULL) {
+ listener->onBuffersReleased();
+ }
+}
+
void SurfaceFlingerConsumer::onSidebandStreamChanged() {
sp<ContentsChangedListener> listener;
{ // scope for the lock
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index d3f0070..7713ed2 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -33,6 +33,7 @@
static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
struct ContentsChangedListener: public FrameAvailableListener {
+ virtual void onBuffersReleased() = 0;
virtual void onSidebandStreamChanged() = 0;
};
@@ -89,6 +90,7 @@
FrameEventHistoryDelta* outDelta) override;
private:
+ virtual void onBuffersReleased();
virtual void onSidebandStreamChanged();
wp<ContentsChangedListener> mContentsChangedListener;