Merge "Fix potential synchronized race between SF and InputFlinger" into sc-dev
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6497919..df98eb6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3105,7 +3105,7 @@
void SurfaceFlinger::commitTransaction() {
commitTransactionLocked();
- signalSynchronousTransactions();
+ signalSynchronousTransactions(CountDownLatch::eSyncTransaction);
mAnimTransactionPending = false;
}
@@ -3527,7 +3527,9 @@
// Generate a CountDownLatch pending state if this is a synchronous transaction.
if ((state.flags & eSynchronous) || state.inputWindowCommands.syncInputWindows) {
state.transactionCommittedSignal = std::make_shared<CountDownLatch>(
- (state.inputWindowCommands.syncInputWindows ? 2 : 1));
+ (state.inputWindowCommands.syncInputWindows
+ ? (CountDownLatch::eSyncInputWindows | CountDownLatch::eSyncTransaction)
+ : CountDownLatch::eSyncTransaction));
}
mTransactionQueue.emplace(state);
@@ -3552,10 +3554,10 @@
}
}
-void SurfaceFlinger::signalSynchronousTransactions() {
+void SurfaceFlinger::signalSynchronousTransactions(const uint32_t flag) {
for (auto it = mTransactionCommittedSignals.begin();
it != mTransactionCommittedSignals.end();) {
- if ((*it)->countDown() == 0) {
+ if ((*it)->countDown(flag)) {
it = mTransactionCommittedSignals.erase(it);
} else {
it++;
@@ -6175,7 +6177,7 @@
void SurfaceFlinger::setInputWindowsFinished() {
Mutex::Autolock _l(mStateLock);
- signalSynchronousTransactions();
+ signalSynchronousTransactions(CountDownLatch::eSyncInputWindows);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index cf1a545..4bbdd48 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -467,24 +467,31 @@
class CountDownLatch {
public:
- explicit CountDownLatch(int32_t count) : mCount(count) {}
+ enum {
+ eSyncTransaction = 1 << 0,
+ eSyncInputWindows = 1 << 1,
+ };
+ explicit CountDownLatch(uint32_t flags) : mFlags(flags) {}
- int32_t countDown() {
+ // True if there is no waiting condition after count down.
+ bool countDown(uint32_t flag) {
std::unique_lock<std::mutex> lock(mMutex);
- if (mCount == 0) {
- return 0;
+ if (mFlags == 0) {
+ return true;
}
- if (--mCount == 0) {
+ mFlags &= ~flag;
+ if (mFlags == 0) {
mCountDownComplete.notify_all();
+ return true;
}
- return mCount;
+ return false;
}
// Return true if triggered.
bool wait_until(const std::chrono::seconds& timeout) const {
std::unique_lock<std::mutex> lock(mMutex);
const auto untilTime = std::chrono::system_clock::now() + timeout;
- while (mCount != 0) {
+ while (mFlags != 0) {
// Conditional variables can be woken up sporadically, so we check count
// to verify the wakeup was triggered by |countDown|.
if (std::cv_status::timeout == mCountDownComplete.wait_until(lock, untilTime)) {
@@ -495,7 +502,7 @@
}
private:
- int32_t mCount;
+ uint32_t mFlags;
mutable std::condition_variable mCountDownComplete;
mutable std::mutex mMutex;
};
@@ -1124,7 +1131,7 @@
// Add transaction to the Transaction Queue
void queueTransaction(TransactionState& state) EXCLUDES(mQueueLock);
void waitForSynchronousTransaction(const CountDownLatch& transactionCommittedSignal);
- void signalSynchronousTransactions();
+ void signalSynchronousTransactions(const uint32_t flag);
/*
* Generic Layer Metadata