Store SurfaceControl reference when creating transactions
The SurfaceControl needs to be stored when adding a new transaction.
This ensures the ref count is incremented so the SC isn't removed before
the transaction is applied.
Change-Id: I27a060e4c221c5dfa565ceb3a916574105fd1175
Fixes: 73448047
Test: DereferenceSurfaceControlTest
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index b7773c4..92a24ad 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -105,12 +105,11 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
- for (auto const& state : other.mComposerStates) {
- ssize_t index = mComposerStates.indexOf(state);
- if (index < 0) {
- mComposerStates.add(state);
+ for (auto const& kv : other.mComposerStates) {
+ if (mComposerStates.count(kv.first) == 0) {
+ mComposerStates[kv.first] = kv.second;
} else {
- mComposerStates.editItemAt(static_cast<size_t>(index)).state.merge(state.state);
+ mComposerStates[kv.first].state.merge(kv.second.state);
}
}
other.mComposerStates.clear();
@@ -141,7 +140,10 @@
mForceSynchronous |= synchronous;
- composerStates = mComposerStates;
+ for (auto const& kv : mComposerStates){
+ composerStates.add(kv.second);
+ }
+
mComposerStates.clear();
displayStates = mDisplayStates;
@@ -182,18 +184,15 @@
}
layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) {
- ComposerState s;
- s.client = sc->getClient()->mClient;
- s.state.surface = sc->getHandle();
-
- ssize_t index = mComposerStates.indexOf(s);
- if (index < 0) {
+ if (mComposerStates.count(sc) == 0) {
// we don't have it, add an initialized layer_state to our list
- index = mComposerStates.add(s);
+ ComposerState s;
+ s.client = sc->getClient()->mClient;
+ s.state.surface = sc->getHandle();
+ mComposerStates[sc] = s;
}
- ComposerState* const out = mComposerStates.editArray();
- return &(out[index].state);
+ return &(mComposerStates[sc].state);
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition(
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index e5156c6..3fe6635 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <unordered_map>
#include <binder/IBinder.h>
@@ -127,8 +128,14 @@
static status_t injectVSync(nsecs_t when);
+ struct SCHash {
+ std::size_t operator()(const sp<SurfaceControl>& sc) const {
+ return std::hash<SurfaceControl *>{}(sc.get());
+ }
+ };
+
class Transaction {
- SortedVector<ComposerState> mComposerStates;
+ std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> mComposerStates;
SortedVector<DisplayState > mDisplayStates;
uint32_t mForceSynchronous = 0;
uint32_t mTransactionNestCount = 0;