Revert "Introduce SurfaceFlinger Queued Transaction"
This reverts commit 3e95285e5bc67a5e5a33ac72e3fff3f234b24de8.
Reason for revert: broken test b/169245126
Bug: 169245126
Change-Id: I9d4b01619433a31ad8d8b2698926599359322e83
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 78c0a0e..f1f67cc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1896,18 +1896,19 @@
bool SurfaceFlinger::handleMessageTransaction() {
ATRACE_CALL();
-
- if (getTransactionFlags(eTransactionFlushNeeded)) {
- flushPendingTransactionQueues();
- flushTransactionQueue();
- }
-
uint32_t transactionFlags = peekTransactionFlags();
+
+ bool flushedATransaction = flushTransactionQueues();
+
bool runHandleTransaction =
- (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) || mForceTraversal;
+ (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
+ flushedATransaction ||
+ mForceTraversal;
if (runHandleTransaction) {
handleTransaction(eTransactionMask);
+ } else {
+ getTransactionFlags(eTransactionFlushNeeded);
}
if (transactionFlushNeeded()) {
@@ -2776,6 +2777,7 @@
});
}
+ commitInputWindowCommands();
commitTransaction();
}
@@ -2816,6 +2818,11 @@
: nullptr);
}
+void SurfaceFlinger::commitInputWindowCommands() {
+ mInputWindowCommands.merge(mPendingInputWindowCommands);
+ mPendingInputWindowCommands.clear();
+}
+
void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
@@ -3168,52 +3175,50 @@
mForceTraversal = true;
}
-void SurfaceFlinger::flushPendingTransactionQueues() {
+bool SurfaceFlinger::flushTransactionQueues() {
// to prevent onHandleDestroyed from being called while the lock is held,
// we must keep a copy of the transactions (specifically the composer
// states) around outside the scope of the lock
std::vector<const TransactionState> transactions;
+ bool flushedATransaction = false;
{
- Mutex::Autolock _l(mQueueLock);
+ Mutex::Autolock _l(mStateLock);
- auto it = mPendingTransactionQueues.begin();
- while (it != mPendingTransactionQueues.end()) {
+ auto it = mTransactionQueues.begin();
+ while (it != mTransactionQueues.end()) {
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
const auto& transaction = transactionQueue.front();
if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
transaction.states)) {
+ setTransactionFlags(eTransactionFlushNeeded);
break;
}
transactions.push_back(transaction);
+ applyTransactionState(transaction.states, transaction.displays, transaction.flags,
+ mPendingInputWindowCommands, transaction.desiredPresentTime,
+ transaction.buffer, transaction.postTime,
+ transaction.privileged, transaction.hasListenerCallbacks,
+ transaction.listenerCallbacks, transaction.originPID,
+ transaction.originUID, /*isMainThread*/ true);
transactionQueue.pop();
+ flushedATransaction = true;
}
if (transactionQueue.empty()) {
- it = mPendingTransactionQueues.erase(it);
+ it = mTransactionQueues.erase(it);
mTransactionCV.broadcast();
} else {
it = std::next(it, 1);
}
}
}
-
- {
- Mutex::Autolock _l(mStateLock);
- for (const auto& transaction : transactions) {
- applyTransactionState(transaction.states, transaction.displays, transaction.flags,
- mInputWindowCommands, transaction.desiredPresentTime,
- transaction.buffer, transaction.postTime, transaction.privileged,
- transaction.hasListenerCallbacks, transaction.listenerCallbacks,
- transaction.originPID, transaction.originUID);
- }
- }
+ return flushedATransaction;
}
bool SurfaceFlinger::transactionFlushNeeded() {
- Mutex::Autolock _l(mQueueLock);
- return !mPendingTransactionQueues.empty();
+ return !mTransactionQueues.empty();
}
@@ -3248,125 +3253,51 @@
ATRACE_CALL();
const int64_t postTime = systemTime();
+
bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
- {
- Mutex::Autolock _l(mQueueLock);
-
- // If its TransactionQueue already has a pending TransactionState or if it is pending
- auto itr = mPendingTransactionQueues.find(applyToken);
- // if this is an animation frame, wait until prior animation frame has
- // been applied by SF
- if (flags & eAnimation) {
- while (itr != mPendingTransactionQueues.end()) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- ALOGW_IF(err == TIMED_OUT,
- "setTransactionState timed out "
- "waiting for animation frame to apply");
- break;
- }
- itr = mPendingTransactionQueues.find(applyToken);
- }
- }
-
- // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
- if (flags & eEarlyWakeup) {
- ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
- }
-
- if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
- ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
- flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
- }
-
- const bool pendingTransactions = itr != mPendingTransactionQueues.end();
- // Expected present time is computed and cached on invalidate, so it may be stale.
- if (!pendingTransactions) {
- mExpectedPresentTime = calculateExpectedPresentTime(systemTime());
- }
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPID = ipc->getCallingPid();
- const int originUID = ipc->getCallingUid();
-
- if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
- mPendingTransactionQueues[applyToken].emplace(states, displays, flags,
- inputWindowCommands, desiredPresentTime,
- uncacheBuffer, postTime, privileged,
- hasListenerCallbacks, listenerCallbacks,
- originPID, originUID);
- setTransactionFlags(eTransactionFlushNeeded);
- return NO_ERROR;
- }
-
- mTransactionQueue.emplace_back(states, displays, flags, inputWindowCommands,
- desiredPresentTime, uncacheBuffer, postTime, privileged,
- hasListenerCallbacks, listenerCallbacks, originPID,
- originUID);
- }
-
- {
- Mutex::Autolock _l(mStateLock);
-
- const auto schedule = [](uint32_t flags) {
- if (flags & eEarlyWakeup) return TransactionSchedule::Early;
- if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
- if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
- return TransactionSchedule::Late;
- }(flags);
-
- // if this is a synchronous transaction, wait for it to take effect
- // before returning.
- const bool synchronous = flags & eSynchronous;
- const bool syncInput = inputWindowCommands.syncInputWindows;
- if (!synchronous && !syncInput) {
- setTransactionFlags(eTransactionFlushNeeded, schedule);
- return NO_ERROR;
- }
-
- if (synchronous) {
- mTransactionPending = true;
- }
- if (syncInput) {
- mPendingSyncInputWindows = true;
- }
- setTransactionFlags(eTransactionFlushNeeded, schedule);
-
- // applyTransactionState can be called by either the main SF thread or by
- // another process through setTransactionState. While a given process may wish
- // to wait on synchronous transactions, the main SF thread should never
- // be blocked. Therefore, we only wait if isMainThread is false.
- while (mTransactionPending || mPendingSyncInputWindows) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
- mTransactionPending = false;
- mPendingSyncInputWindows = false;
- break;
- }
- }
- }
- return NO_ERROR;
-}
-
-void SurfaceFlinger::flushTransactionQueue() {
- std::vector<TransactionState> transactionQueue;
- {
- Mutex::Autolock _l(mQueueLock);
- if (!mTransactionQueue.empty()) {
- transactionQueue.swap(mTransactionQueue);
- }
- }
Mutex::Autolock _l(mStateLock);
- for (const auto& t : transactionQueue) {
- applyTransactionState(t.states, t.displays, t.flags, t.inputWindowCommands,
- t.desiredPresentTime, t.buffer, t.postTime, t.privileged,
- t.hasListenerCallbacks, t.listenerCallbacks, t.originPID,
- t.originUID);
+
+ // If its TransactionQueue already has a pending TransactionState or if it is pending
+ auto itr = mTransactionQueues.find(applyToken);
+ // if this is an animation frame, wait until prior animation frame has
+ // been applied by SF
+ if (flags & eAnimation) {
+ while (itr != mTransactionQueues.end()) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ ALOGW_IF(err == TIMED_OUT,
+ "setTransactionState timed out "
+ "waiting for animation frame to apply");
+ break;
+ }
+ itr = mTransactionQueues.find(applyToken);
+ }
}
+
+ const bool pendingTransactions = itr != mTransactionQueues.end();
+ // Expected present time is computed and cached on invalidate, so it may be stale.
+ if (!pendingTransactions) {
+ mExpectedPresentTime = calculateExpectedPresentTime(systemTime());
+ }
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPID = ipc->getCallingPid();
+ const int originUID = ipc->getCallingUid();
+
+ if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
+ mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
+ uncacheBuffer, postTime, privileged,
+ hasListenerCallbacks, listenerCallbacks, originPID,
+ originUID);
+ setTransactionFlags(eTransactionFlushNeeded);
+ return NO_ERROR;
+ }
+
+ applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime,
+ uncacheBuffer, postTime, privileged, hasListenerCallbacks,
+ listenerCallbacks, originPID, originUID, /*isMainThread*/ false);
+ return NO_ERROR;
}
void SurfaceFlinger::applyTransactionState(
@@ -3374,9 +3305,25 @@
const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged,
bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
- int32_t originPID, int32_t originUID) {
+ int originPID, int originUID, bool isMainThread) {
uint32_t transactionFlags = 0;
+ if (flags & eAnimation) {
+ // For window updates that are part of an animation we must wait for
+ // previous animation "frames" to be handled.
+ while (!isMainThread && mAnimTransactionPending) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // caller after a few seconds.
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
+ "waiting for previous animation frame");
+ mAnimTransactionPending = false;
+ break;
+ }
+ }
+ }
+
for (const DisplayState& display : displays) {
transactionFlags |= setDisplayStateLocked(display);
}
@@ -3432,25 +3379,80 @@
transactionFlags = eTransactionNeeded;
}
- if (transactionFlags && mInterceptor->isEnabled()) {
- mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags, originPID,
- originUID);
- }
-
- // We are on the main thread, we are about to preform a traversal. Clear the traversal bit
- // so we don't have to wake up again next frame to preform an unnecessary traversal.
- if (transactionFlags & eTraversalNeeded) {
+ // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
+ // so we don't have to wake up again next frame to preform an uneeded traversal.
+ if (isMainThread && (transactionFlags & eTraversalNeeded)) {
transactionFlags = transactionFlags & (~eTraversalNeeded);
mForceTraversal = true;
}
+ const auto schedule = [](uint32_t flags) {
+ if (flags & eEarlyWakeup) return TransactionSchedule::Early;
+ if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
+ if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
+ return TransactionSchedule::Late;
+ }(flags);
+
if (transactionFlags) {
+ if (mInterceptor->isEnabled()) {
+ mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags,
+ originPID, originUID);
+ }
+
+ // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
+ if (flags & eEarlyWakeup) {
+ ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ }
+
+ if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
+ ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
+ flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ }
+
// this triggers the transaction
- setTransactionFlags(transactionFlags);
+ setTransactionFlags(transactionFlags, schedule);
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
+
+ // if this is a synchronous transaction, wait for it to take effect
+ // before returning.
+ const bool synchronous = flags & eSynchronous;
+ const bool syncInput = inputWindowCommands.syncInputWindows;
+ if (!synchronous && !syncInput) {
+ return;
+ }
+
+ if (synchronous) {
+ mTransactionPending = true;
+ }
+ if (syncInput) {
+ mPendingSyncInputWindows = true;
+ }
+
+
+ // applyTransactionState can be called by either the main SF thread or by
+ // another process through setTransactionState. While a given process may wish
+ // to wait on synchronous transactions, the main SF thread should never
+ // be blocked. Therefore, we only wait if isMainThread is false.
+ while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+ mTransactionPending = false;
+ mPendingSyncInputWindows = false;
+ break;
+ }
+ }
+ } else {
+ // Update VsyncModulator state machine even if transaction is not needed.
+ if (schedule == TransactionSchedule::EarlyStart ||
+ schedule == TransactionSchedule::EarlyEnd) {
+ modulateVsync(&VsyncModulator::setTransactionSchedule, schedule);
+ }
}
}
@@ -3829,7 +3831,7 @@
}
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
- bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
+ bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
return hasChanges ? eTraversalNeeded : 0;
}
@@ -4107,9 +4109,8 @@
d.width = 0;
d.height = 0;
displays.add(d);
- // This called on the main thread, apply it directly.
- applyTransactionState(state, displays, 0, mInputWindowCommands, -1, {}, systemTime(), true,
- false, {}, getpid(), getuid());
+ setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}, false,
+ {});
setPowerModeInternal(display, hal::PowerMode::ON);
const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -5273,7 +5274,7 @@
void SurfaceFlinger::repaintEverything() {
mRepaintEverything = true;
- setTransactionFlags(eTransactionNeeded);
+ signalTransaction();
}
void SurfaceFlinger::repaintEverythingForHWC() {