Merge "Set refresh rate stats correctly on SF initialization."
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 36d5a60..fa2b0d9 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -936,8 +936,7 @@
protected:
void TransitionToSystemServer() {
ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid));
- int32_t res = selinux_android_setcontext(
- kSystemUid, true, se_info_.c_str(), "system_server");
+ int32_t res = selinux_android_setcon("u:r:system_server:s0");
ASSERT_EQ(0, res) << "Failed to setcon " << strerror(errno);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 247dc8d..bc63d31 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -68,7 +68,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& commands,
- int64_t desiredPresentTime) {
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -86,6 +87,8 @@
data.writeStrongBinder(applyToken);
commands.write(data);
data.writeInt64(desiredPresentTime);
+ data.writeStrongBinder(uncacheBuffer.token);
+ data.writeUint64(uncacheBuffer.cacheId);
remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
@@ -970,8 +973,13 @@
inputWindowCommands.read(data);
int64_t desiredPresentTime = data.readInt64();
+
+ cached_buffer_t uncachedBuffer;
+ uncachedBuffer.token = data.readStrongBinder();
+ uncachedBuffer.cacheId = data.readUint64();
+
setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands,
- desiredPresentTime);
+ desiredPresentTime, uncachedBuffer);
return NO_ERROR;
}
case BOOT_FINISHED: {
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 84ba644..f6ca9e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -95,7 +95,7 @@
}
output.writeStrongBinder(cachedBuffer.token);
- output.writeInt32(cachedBuffer.bufferId);
+ output.writeUint64(cachedBuffer.cacheId);
output.writeParcelable(metadata);
output.writeFloat(bgColorAlpha);
@@ -173,7 +173,7 @@
}
cachedBuffer.token = input.readStrongBinder();
- cachedBuffer.bufferId = input.readInt32();
+ cachedBuffer.cacheId = input.readUint64();
input.readParcelable(&metadata);
bgColorAlpha = input.readFloat();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index b0e8275..39cd62f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -233,6 +233,8 @@
// ---------------------------------------------------------------------------
+void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId);
+
class BufferCache : public Singleton<BufferCache> {
public:
BufferCache() : token(new BBinder()) {}
@@ -241,77 +243,57 @@
return IInterface::asBinder(TransactionCompletedListener::getIInstance());
}
- int32_t getId(const sp<GraphicBuffer>& buffer) {
+ status_t getCacheId(const sp<GraphicBuffer>& buffer, uint64_t* cacheId) {
std::lock_guard<std::mutex> lock(mMutex);
- auto itr = mBuffers.find(buffer);
+ auto itr = mBuffers.find(buffer->getId());
if (itr == mBuffers.end()) {
- return -1;
+ return BAD_VALUE;
}
- itr->second.counter = getCounter();
- return itr->second.id;
+ itr->second = getCounter();
+ *cacheId = buffer->getId();
+ return NO_ERROR;
}
- int32_t cache(const sp<GraphicBuffer>& buffer) {
+ uint64_t cache(const sp<GraphicBuffer>& buffer) {
std::lock_guard<std::mutex> lock(mMutex);
- int32_t bufferId = getNextAvailableId();
+ if (mBuffers.size() >= BUFFER_CACHE_MAX_SIZE) {
+ evictLeastRecentlyUsedBuffer();
+ }
- mBuffers[buffer].id = bufferId;
- mBuffers[buffer].counter = getCounter();
- return bufferId;
+ buffer->addDeathCallback(bufferCacheCallback, nullptr);
+
+ mBuffers[buffer->getId()] = getCounter();
+ return buffer->getId();
+ }
+
+ void uncache(uint64_t cacheId) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ uncacheLocked(cacheId);
+ }
+
+ void uncacheLocked(uint64_t cacheId) REQUIRES(mMutex) {
+ mBuffers.erase(cacheId);
+ SurfaceComposerClient::doUncacheBufferTransaction(cacheId);
}
private:
- int32_t evictDestroyedBuffer() REQUIRES(mMutex) {
+ void evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
auto itr = mBuffers.begin();
- while (itr != mBuffers.end()) {
- auto& buffer = itr->first;
- if (buffer == nullptr || buffer.promote() == nullptr) {
- int32_t bufferId = itr->second.id;
- mBuffers.erase(itr);
- return bufferId;
- }
- itr++;
- }
- return -1;
- }
-
- int32_t evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) {
- if (mBuffers.size() < 0) {
- return -1;
- }
- auto itr = mBuffers.begin();
- uint64_t minCounter = itr->second.counter;
+ uint64_t minCounter = itr->second;
auto minBuffer = itr;
itr++;
while (itr != mBuffers.end()) {
- uint64_t counter = itr->second.counter;
+ uint64_t counter = itr->second;
if (counter < minCounter) {
minCounter = counter;
minBuffer = itr;
}
itr++;
}
- int32_t minBufferId = minBuffer->second.id;
- mBuffers.erase(minBuffer);
- return minBufferId;
- }
-
- int32_t getNextAvailableId() REQUIRES(mMutex) {
- static int32_t id = 0;
- if (id + 1 < BUFFER_CACHE_MAX_SIZE) {
- return id++;
- }
-
- // There are no more valid cache ids. To set additional buffers, evict existing buffers
- // and reuse their cache ids.
- int32_t bufferId = evictDestroyedBuffer();
- if (bufferId > 0) {
- return bufferId;
- }
- return evictLeastRecentlyUsedBuffer();
+ uncacheLocked(minBuffer->first);
}
uint64_t getCounter() REQUIRES(mMutex) {
@@ -319,18 +301,8 @@
return counter++;
}
- struct Metadata {
- // The cache id of a buffer that can be set to ISurfaceComposer. When ISurfaceComposer
- // recieves this id, it can retrieve the buffer from its cache. Caching GraphicBuffers
- // is important because sending them across processes is expensive.
- int32_t id = 0;
- // When a buffer is set, a counter is incremented and stored in the cache's metadata.
- // When an buffer must be evicted, the entry with the lowest counter value is chosen.
- uint64_t counter = 0;
- };
-
std::mutex mMutex;
- std::map<wp<GraphicBuffer>, Metadata> mBuffers GUARDED_BY(mMutex);
+ std::map<uint64_t /*Cache id*/, uint64_t /*counter*/> mBuffers GUARDED_BY(mMutex);
// Used by ISurfaceComposer to identify which process is sending the cached buffer.
sp<IBinder> token;
@@ -338,6 +310,11 @@
ANDROID_SINGLETON_STATIC_INSTANCE(BufferCache);
+void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId) {
+ // GraphicBuffer id's are used as the cache ids.
+ BufferCache::getInstance().uncache(graphicBufferId);
+}
+
// ---------------------------------------------------------------------------
SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
@@ -385,6 +362,9 @@
mInputWindowCommands.merge(other.mInputWindowCommands);
other.mInputWindowCommands.clear();
+ mContainsBuffer = other.mContainsBuffer;
+ other.mContainsBuffer = false;
+
return *this;
}
@@ -401,7 +381,50 @@
s.state.parentHandleForChild = nullptr;
composerStates.add(s);
- sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1);
+ sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {});
+}
+
+void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+ cached_buffer_t uncacheBuffer;
+ uncacheBuffer.token = BufferCache::getInstance().getToken();
+ uncacheBuffer.cacheId = cacheId;
+
+ sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer);
+}
+
+void SurfaceComposerClient::Transaction::cacheBuffers() {
+ if (!mContainsBuffer) {
+ return;
+ }
+
+ size_t count = 0;
+ for (auto& [sc, cs] : mComposerStates) {
+ layer_state_t* s = getLayerState(sc);
+ if (!(s->what & layer_state_t::eBufferChanged)) {
+ continue;
+ }
+
+ uint64_t cacheId = 0;
+ status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId);
+ if (ret == NO_ERROR) {
+ s->what &= ~static_cast<uint32_t>(layer_state_t::eBufferChanged);
+ s->buffer = nullptr;
+ } else {
+ cacheId = BufferCache::getInstance().cache(s->buffer);
+ }
+ s->what |= layer_state_t::eCachedBufferChanged;
+ s->cachedBuffer.token = BufferCache::getInstance().getToken();
+ s->cachedBuffer.cacheId = cacheId;
+
+ // If we have more buffers than the size of the cache, we should stop caching so we don't
+ // evict other buffers in this transaction
+ count++;
+ if (count >= BUFFER_CACHE_MAX_SIZE) {
+ break;
+ }
+ }
}
status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
@@ -437,6 +460,8 @@
}
mListenerCallbacks.clear();
+ cacheBuffers();
+
Vector<ComposerState> composerStates;
Vector<DisplayState> displayStates;
uint32_t flags = 0;
@@ -468,7 +493,8 @@
sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands,
- mDesiredPresentTime);
+ mDesiredPresentTime,
+ {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/);
mInputWindowCommands.clear();
mStatus = NO_ERROR;
return NO_ERROR;
@@ -882,20 +908,12 @@
mStatus = BAD_INDEX;
return *this;
}
-
- int32_t bufferId = BufferCache::getInstance().getId(buffer);
- if (bufferId < 0) {
- bufferId = BufferCache::getInstance().cache(buffer);
-
- s->what |= layer_state_t::eBufferChanged;
- s->buffer = buffer;
- }
-
- s->what |= layer_state_t::eCachedBufferChanged;
- s->cachedBuffer.token = BufferCache::getInstance().getToken();
- s->cachedBuffer.bufferId = bufferId;
+ s->what |= layer_state_t::eBufferChanged;
+ s->buffer = buffer;
registerSurfaceControlForCallback(sc);
+
+ mContainsBuffer = true;
return *this;
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 8f54fee..0ef5b39 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -40,6 +40,7 @@
namespace android {
// ----------------------------------------------------------------------------
+struct cached_buffer_t;
struct ComposerState;
struct DisplayState;
struct DisplayInfo;
@@ -131,7 +132,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime) = 0;
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) = 0;
/* signal that we're done booting.
* Requires ACCESS_SURFACE_FLINGER permission
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 35e795c..77bf8f1 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -41,6 +41,11 @@
class Parcel;
class ISurfaceComposerClient;
+struct cached_buffer_t {
+ sp<IBinder> token = nullptr;
+ uint64_t cacheId;
+};
+
/*
* Used to communicate layer information between SurfaceFlinger and its clients.
*/
@@ -133,10 +138,6 @@
float dtdy{0};
float dsdy{0};
};
- struct cached_buffer_t {
- sp<IBinder> token = nullptr;
- int32_t bufferId = -1;
- };
sp<IBinder> surface;
uint64_t what;
float x;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 39d6d13..593a5e7 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -165,6 +165,12 @@
static void doDropReferenceTransaction(const sp<IBinder>& handle,
const sp<ISurfaceComposerClient>& client);
+ /**
+ * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is
+ * in order with other transactions that use buffers.
+ */
+ static void doUncacheBufferTransaction(uint64_t cacheId);
+
// Queries whether a given display is wide color display.
static status_t isWideColorDisplay(const sp<IBinder>& display, bool* outIsWideColorDisplay);
@@ -279,6 +285,9 @@
bool mAnimation = false;
bool mEarlyWakeup = false;
+ // Indicates that the Transaction contains a buffer that should be cached
+ bool mContainsBuffer = false;
+
// mDesiredPresentTime is the time in nanoseconds that the client would like the transaction
// to be presented. When it is not possible to present at exactly that time, it will be
// presented after the time has passed.
@@ -297,6 +306,7 @@
layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
DisplayState& getDisplayState(const sp<IBinder>& token);
+ void cacheBuffers();
void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc);
public:
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 06fe86c..94b669d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -560,7 +560,8 @@
const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/,
const InputWindowCommands& /*inputWindowCommands*/,
- int64_t /*desiredPresentTime*/) override {}
+ int64_t /*desiredPresentTime*/,
+ const cached_buffer_t& /*cachedBuffer*/) override {}
void bootFinished() override {}
bool authenticateSurfaceTexture(
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
index 49bdd2a..cd1182c 100644
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ b/libs/renderengine/gl/ProgramCache.cpp
@@ -102,14 +102,21 @@
// Prime for sRGB->P3 conversion
if (useColorManagement) {
Key shaderKey;
- shaderKey.set(Key::BLEND_MASK | Key::TEXTURE_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK |
- Key::INPUT_TF_MASK | Key::OUTPUT_TF_MASK,
- Key::BLEND_PREMULT | Key::TEXTURE_EXT | Key::OUTPUT_TRANSFORM_MATRIX_ON |
- Key::INPUT_TF_SRGB | Key::OUTPUT_TF_SRGB);
- for (int i = 0; i < 4; i++) {
+ shaderKey.set(Key::BLEND_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK | Key::INPUT_TF_MASK |
+ Key::OUTPUT_TF_MASK,
+ Key::BLEND_PREMULT | Key::OUTPUT_TRANSFORM_MATRIX_ON | Key::INPUT_TF_SRGB |
+ Key::OUTPUT_TF_SRGB);
+ for (int i = 0; i < 16; i++) {
shaderKey.set(Key::OPACITY_MASK,
(i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT);
shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE);
+
+ // Cache rounded corners
+ shaderKey.set(Key::ROUNDED_CORNERS_MASK,
+ (i & 4) ? Key::ROUNDED_CORNERS_ON : Key::ROUNDED_CORNERS_OFF);
+
+ // Cache texture off option for window transition
+ shaderKey.set(Key::TEXTURE_MASK, (i & 8) ? Key::TEXTURE_EXT : Key::TEXTURE_OFF);
if (cache.count(shaderKey) == 0) {
cache.emplace(shaderKey, generateProgram(shaderKey));
shaderCount++;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index e1c325e..40df260 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -133,6 +133,9 @@
if (handle) {
free_handle();
}
+ for (auto& [callback, context] : mDeathCallbacks) {
+ callback(context, mId);
+ }
}
void GraphicBuffer::free_handle()
@@ -553,6 +556,10 @@
return NO_ERROR;
}
+void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) {
+ mDeathCallbacks.emplace_back(deathCallback, context);
+}
+
#ifndef LIBUI_IN_VNDK
status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds,
size_t& count) const {
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index cb4ee2a..c137860 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -21,6 +21,8 @@
#include <sys/types.h>
#include <string>
+#include <utility>
+#include <vector>
#include <android/hardware_buffer.h>
#include <ui/ANativeObjectBase.h>
@@ -42,6 +44,8 @@
class GraphicBufferMapper;
+using GraphicBufferDeathCallback = std::function<void(void* /*context*/, uint64_t bufferId)>;
+
// ===========================================================================
// GraphicBuffer
// ===========================================================================
@@ -219,6 +223,8 @@
return mBufferMapper.getMapperVersion();
}
+ void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context);
+
#ifndef LIBUI_IN_VNDK
// Returns whether this GraphicBuffer is backed by BufferHubBuffer.
bool isBufferHubBuffer() const;
@@ -280,6 +286,20 @@
// IGBP::setGenerationNumber), attempts to attach the buffer will fail.
uint32_t mGenerationNumber;
+ // Send a callback when a GraphicBuffer dies.
+ //
+ // This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When
+ // A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes
+ // problems when trying to implicitcly cache across process boundaries. Ideally, both sides
+ // of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer
+ // would be destroyed. Unfortunately, when SurfaceFlinger has only a wp<> reference to the
+ // GraphicBuffer, it immediately goes out of scope in the SurfaceFlinger process. SurfaceFlinger
+ // must hold onto a sp<> to the buffer. When the GraphicBuffer goes out of scope in the app's
+ // process, the client side cache will get this callback. It erases the buffer from its cache
+ // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer.
+ std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>>
+ mDeathCallbacks;
+
#ifndef LIBUI_IN_VNDK
// Flatten this GraphicBuffer object if backed by BufferHubBuffer.
status_t flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, size_t& count) const;
diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp
index cb02d16..51ca45c 100644
--- a/services/surfaceflinger/BufferStateLayerCache.cpp
+++ b/services/surfaceflinger/BufferStateLayerCache.cpp
@@ -23,21 +23,14 @@
#include "BufferStateLayerCache.h"
-#define VALID_CACHE_ID(id) ((id) >= 0 || (id) < (BUFFER_CACHE_MAX_SIZE))
-
namespace android {
ANDROID_SINGLETON_STATIC_INSTANCE(BufferStateLayerCache);
BufferStateLayerCache::BufferStateLayerCache() : mDeathRecipient(new CacheDeathRecipient) {}
-void BufferStateLayerCache::add(sp<IBinder> processToken, int32_t id,
+void BufferStateLayerCache::add(const sp<IBinder>& processToken, uint64_t id,
const sp<GraphicBuffer>& buffer) {
- if (!VALID_CACHE_ID(id)) {
- ALOGE("failed to cache buffer: invalid buffer id");
- return;
- }
-
if (!processToken) {
ALOGE("failed to cache buffer: invalid process token");
return;
@@ -61,15 +54,33 @@
}
auto& processBuffers = mBuffers[processToken];
+
+ if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
+ ALOGE("failed to cache buffer: cache is full");
+ return;
+ }
+
processBuffers[id] = buffer;
}
-sp<GraphicBuffer> BufferStateLayerCache::get(sp<IBinder> processToken, int32_t id) {
- if (!VALID_CACHE_ID(id)) {
- ALOGE("failed to get buffer: invalid buffer id");
- return nullptr;
+void BufferStateLayerCache::erase(const sp<IBinder>& processToken, uint64_t id) {
+ if (!processToken) {
+ ALOGE("failed to uncache buffer: invalid process token");
+ return;
}
+ std::lock_guard lock(mMutex);
+
+ if (mBuffers.find(processToken) == mBuffers.end()) {
+ ALOGE("failed to uncache buffer: process token not found");
+ return;
+ }
+
+ auto& processBuffers = mBuffers[processToken];
+ processBuffers.erase(id);
+}
+
+sp<GraphicBuffer> BufferStateLayerCache::get(const sp<IBinder>& processToken, uint64_t id) {
if (!processToken) {
ALOGE("failed to cache buffer: invalid process token");
return nullptr;
@@ -82,8 +93,8 @@
return nullptr;
}
- if (id >= itr->second.size()) {
- ALOGE("failed to get buffer: id outside the bounds of the cache");
+ if (itr->second.find(id) == itr->second.end()) {
+ ALOGE("failed to get buffer: buffer not found");
return nullptr;
}
diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h
index ede3feb..415c09c 100644
--- a/services/surfaceflinger/BufferStateLayerCache.h
+++ b/services/surfaceflinger/BufferStateLayerCache.h
@@ -34,14 +34,16 @@
public:
BufferStateLayerCache();
- void add(sp<IBinder> processToken, int32_t id, const sp<GraphicBuffer>& buffer);
- sp<GraphicBuffer> get(sp<IBinder> processToken, int32_t id);
+ void add(const sp<IBinder>& processToken, uint64_t id, const sp<GraphicBuffer>& buffer);
+ void erase(const sp<IBinder>& processToken, uint64_t id);
+
+ sp<GraphicBuffer> get(const sp<IBinder>& processToken, uint64_t id);
void removeProcess(const wp<IBinder>& processToken);
private:
std::mutex mMutex;
- std::map<wp<IBinder> /*caching process*/, std::array<sp<GraphicBuffer>, BUFFER_CACHE_MAX_SIZE>>
+ std::map<wp<IBinder> /*caching process*/, std::map<uint64_t /*Cache id*/, sp<GraphicBuffer>>>
mBuffers GUARDED_BY(mMutex);
class CacheDeathRecipient : public IBinder::DeathRecipient {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6ee64e0..63a1e4f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3509,13 +3509,15 @@
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
- const auto& [states, displays, flags, desiredPresentTime, postTime, privileged] =
- transactionQueue.front();
+ const auto&
+ [states, displays, flags, desiredPresentTime, uncacheBuffer, postTime,
+ privileged] = transactionQueue.front();
if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
break;
}
applyTransactionState(states, displays, flags, mPendingInputWindowCommands,
- desiredPresentTime, postTime, privileged, /*isMainThread*/ true);
+ desiredPresentTime, uncacheBuffer, postTime, privileged,
+ /*isMainThread*/ true);
transactionQueue.pop();
}
@@ -3572,7 +3574,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime) {
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) {
ATRACE_CALL();
const int64_t postTime = systemTime();
@@ -3589,20 +3592,22 @@
if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
- postTime, privileged);
+ uncacheBuffer, postTime, privileged);
setTransactionFlags(eTransactionNeeded);
return;
}
applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime,
- postTime, privileged);
+ uncacheBuffer, postTime, privileged);
}
void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
- const int64_t desiredPresentTime, const int64_t postTime,
- bool privileged, bool isMainThread) {
+ const int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer,
+ const int64_t postTime, bool privileged,
+ bool isMainThread) {
uint32_t transactionFlags = 0;
if (flags & eAnimation) {
@@ -3637,6 +3642,10 @@
transactionFlags |= addInputWindowCommands(inputWindowCommands);
+ if (uncacheBuffer.token) {
+ BufferStateLayerCache::getInstance().erase(uncacheBuffer.token, uncacheBuffer.cacheId);
+ }
+
// If a synchronous transaction is explicitly requested without any changes, force a transaction
// anyway. This can be used as a flush mechanism for previous async transactions.
// Empty animation transaction can be used to simulate back-pressure, so also force a
@@ -3978,16 +3987,20 @@
callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
}
}
-
- if (what & layer_state_t::eBufferChanged) {
- // Add the new buffer to the cache. This should always come before eCachedBufferChanged.
- BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.bufferId,
+ bool bufferChanged = what & layer_state_t::eBufferChanged;
+ bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
+ sp<GraphicBuffer> buffer;
+ if (bufferChanged && cacheIdChanged) {
+ BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.cacheId,
s.buffer);
+ buffer = s.buffer;
+ } else if (cacheIdChanged) {
+ buffer = BufferStateLayerCache::getInstance().get(s.cachedBuffer.token,
+ s.cachedBuffer.cacheId);
+ } else if (bufferChanged) {
+ buffer = s.buffer;
}
- if (what & layer_state_t::eCachedBufferChanged) {
- sp<GraphicBuffer> buffer =
- BufferStateLayerCache::getInstance().get(s.cachedBuffer.token,
- s.cachedBuffer.bufferId);
+ if (buffer) {
if (layer->setBuffer(buffer)) {
flags |= eTraversalNeeded;
layer->setPostTime(postTime);
@@ -4231,7 +4244,7 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1);
+ setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {});
setPowerModeInternal(display, HWC_POWER_MODE_NORMAL);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3bf7c21..26d0cd1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -431,7 +431,8 @@
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime) override;
+ int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer) override;
void bootFinished() override;
bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const override;
@@ -577,7 +578,8 @@
void applyTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
- const int64_t desiredPresentTime, const int64_t postTime,
+ const int64_t desiredPresentTime,
+ const cached_buffer_t& uncacheBuffer, const int64_t postTime,
bool privileged, bool isMainThread = false) REQUIRES(mStateLock);
bool flushTransactionQueues();
uint32_t getTransactionFlags(uint32_t flags);
@@ -1059,11 +1061,13 @@
struct TransactionState {
TransactionState(const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- int64_t desiredPresentTime, int64_t postTime, bool privileged)
+ int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer,
+ int64_t postTime, bool privileged)
: states(composerStates),
displays(displayStates),
flags(transactionFlags),
desiredPresentTime(desiredPresentTime),
+ buffer(uncacheBuffer),
postTime(postTime),
privileged(privileged) {}
@@ -1071,6 +1075,7 @@
Vector<DisplayState> displays;
uint32_t flags;
const int64_t desiredPresentTime;
+ cached_buffer_t buffer;
const int64_t postTime;
bool privileged;
};