SF: check the correct layer state flags for latch unsignaled
A few bug fixes when processing unsignaled buffers.
Bug: 198190384
Test: SF unit tests
Change-Id: I67de78bda55e8f69a54bbd7417bd7446fde4b910
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 40fc342..fccd8f1 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -918,4 +918,183 @@
return mDrawingState.transform.transform(bufferBounds);
}
+bool BufferStateLayer::simpleBufferUpdate(const layer_state_t& s) const {
+ const uint64_t requiredFlags = layer_state_t::eBufferChanged;
+
+ const uint64_t deniedFlags = layer_state_t::eProducerDisconnect | layer_state_t::eLayerChanged |
+ layer_state_t::eRelativeLayerChanged | layer_state_t::eTransparentRegionChanged |
+ layer_state_t::eFlagsChanged | layer_state_t::eBlurRegionsChanged |
+ layer_state_t::eLayerStackChanged | layer_state_t::eAutoRefreshChanged |
+ layer_state_t::eReparent;
+
+ const uint64_t allowedFlags = layer_state_t::eHasListenerCallbacksChanged |
+ layer_state_t::eFrameRateSelectionPriority | layer_state_t::eFrameRateChanged |
+ layer_state_t::eSurfaceDamageRegionChanged | layer_state_t::eApiChanged |
+ layer_state_t::eMetadataChanged | layer_state_t::eDropInputModeChanged |
+ layer_state_t::eInputInfoChanged;
+
+ if ((s.what & requiredFlags) != requiredFlags) {
+ ALOGV("%s: false [missing required flags 0x%" PRIx64 "]", __func__,
+ (s.what | requiredFlags) & ~s.what);
+ return false;
+ }
+
+ if (s.what & deniedFlags) {
+ ALOGV("%s: false [has denied flags 0x%" PRIx64 "]", __func__, s.what & deniedFlags);
+ return false;
+ }
+
+ if (s.what & allowedFlags) {
+ ALOGV("%s: [has allowed flags 0x%" PRIx64 "]", __func__, s.what & allowedFlags);
+ }
+
+ if (s.what & layer_state_t::ePositionChanged) {
+ if (mRequestedTransform.tx() != s.x || mRequestedTransform.ty() != s.y) {
+ ALOGV("%s: false [ePositionChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eAlphaChanged) {
+ if (mDrawingState.color.a != s.alpha) {
+ ALOGV("%s: false [eAlphaChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eColorTransformChanged) {
+ if (mDrawingState.colorTransform != s.colorTransform) {
+ ALOGV("%s: false [eColorTransformChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eBackgroundColorChanged) {
+ if (mDrawingState.bgColorLayer || s.bgColorAlpha != 0) {
+ ALOGV("%s: false [eBackgroundColorChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eMatrixChanged) {
+ if (mRequestedTransform.dsdx() != s.matrix.dsdx ||
+ mRequestedTransform.dtdy() != s.matrix.dtdy ||
+ mRequestedTransform.dtdx() != s.matrix.dtdx ||
+ mRequestedTransform.dsdy() != s.matrix.dsdy) {
+ ALOGV("%s: false [eMatrixChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eCornerRadiusChanged) {
+ if (mDrawingState.cornerRadius != s.cornerRadius) {
+ ALOGV("%s: false [eCornerRadiusChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eBackgroundBlurRadiusChanged) {
+ if (mDrawingState.backgroundBlurRadius != static_cast<int>(s.backgroundBlurRadius)) {
+ ALOGV("%s: false [eBackgroundBlurRadiusChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eTransformChanged) {
+ if (mDrawingState.bufferTransform != s.transform) {
+ ALOGV("%s: false [eTransformChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eTransformToDisplayInverseChanged) {
+ if (mDrawingState.transformToDisplayInverse != s.transformToDisplayInverse) {
+ ALOGV("%s: false [eTransformToDisplayInverseChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eCropChanged) {
+ if (mDrawingState.crop != s.crop) {
+ ALOGV("%s: false [eCropChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eDataspaceChanged) {
+ if (mDrawingState.dataspace != s.dataspace) {
+ ALOGV("%s: false [eDataspaceChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eHdrMetadataChanged) {
+ if (mDrawingState.hdrMetadata != s.hdrMetadata) {
+ ALOGV("%s: false [eHdrMetadataChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eSidebandStreamChanged) {
+ if (mDrawingState.sidebandStream != s.sidebandStream) {
+ ALOGV("%s: false [eSidebandStreamChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eColorSpaceAgnosticChanged) {
+ if (mDrawingState.colorSpaceAgnostic != s.colorSpaceAgnostic) {
+ ALOGV("%s: false [eColorSpaceAgnosticChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eShadowRadiusChanged) {
+ if (mDrawingState.shadowRadius != s.shadowRadius) {
+ ALOGV("%s: false [eShadowRadiusChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eFixedTransformHintChanged) {
+ if (mDrawingState.fixedTransformHint != s.fixedTransformHint) {
+ ALOGV("%s: false [eFixedTransformHintChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eTrustedOverlayChanged) {
+ if (mDrawingState.isTrustedOverlay != s.isTrustedOverlay) {
+ ALOGV("%s: false [eTrustedOverlayChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eStretchChanged) {
+ StretchEffect temp = s.stretchEffect;
+ temp.sanitize();
+ if (mDrawingState.stretchEffect != temp) {
+ ALOGV("%s: false [eStretchChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eBufferCropChanged) {
+ if (mDrawingState.bufferCrop != s.bufferCrop) {
+ ALOGV("%s: false [eBufferCropChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ if (s.what & layer_state_t::eDestinationFrameChanged) {
+ if (mDrawingState.destinationFrame != s.destinationFrame) {
+ ALOGV("%s: false [eDestinationFrameChanged changed]", __func__);
+ return false;
+ }
+ }
+
+ ALOGV("%s: true", __func__);
+ return true;
+}
+
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 248e013..4256212 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -136,6 +136,8 @@
bool bufferNeedsFiltering() const override;
+ bool simpleBufferUpdate(const layer_state_t& s) const override;
+
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ddcd641..e51af1e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -897,6 +897,8 @@
virtual std::string getPendingBufferCounterName() { return ""; }
virtual bool updateGeometry() { return false; }
+ virtual bool simpleBufferUpdate(const layer_state_t&) const { return false; }
+
protected:
friend class impl::SurfaceInterceptor;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b76233c..98199f1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -498,8 +498,6 @@
mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
- enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
-
if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
mTransactionTracing.emplace();
}
@@ -508,11 +506,13 @@
LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
if (base::GetBoolProperty("debug.sf.latch_unsignaled"s, false)) {
return LatchUnsignaledConfig::Always;
- } else if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, false)) {
- return LatchUnsignaledConfig::Auto;
- } else {
- return LatchUnsignaledConfig::Disabled;
}
+
+ if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, false)) {
+ return LatchUnsignaledConfig::AutoSingleLayer;
+ }
+
+ return LatchUnsignaledConfig::Disabled;
}
SurfaceFlinger::~SurfaceFlinger() = default;
@@ -853,6 +853,8 @@
mCompositionEngine->getHwComposer().setCallback(*this);
ClientCache::getInstance().setRenderEngine(&getRenderEngine());
+ enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
+
if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) {
enableHalVirtualDisplays(true);
}
@@ -3640,6 +3642,19 @@
return old;
}
+bool SurfaceFlinger::stopTransactionProcessing(
+ const std::unordered_set<sp<IBinder>, SpHash<IBinder>>&
+ applyTokensWithUnsignaledTransactions) const {
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) {
+ // if we are in LatchUnsignaledConfig::AutoSingleLayer
+ // then we should have only one applyToken for processing.
+ // so we can stop further transactions on this applyToken.
+ return !applyTokensWithUnsignaledTransactions.empty();
+ }
+
+ return false;
+}
+
bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
// to prevent onHandleDestroyed from being called while the lock is held,
// we must keep a copy of the transactions (specifically the composer
@@ -3647,44 +3662,42 @@
std::vector<TransactionState> transactions;
// Layer handles that have transactions with buffers that are ready to be applied.
std::unordered_set<sp<IBinder>, SpHash<IBinder>> bufferLayersReadyToPresent;
+ std::unordered_set<sp<IBinder>, SpHash<IBinder>> applyTokensWithUnsignaledTransactions;
{
Mutex::Autolock _l(mStateLock);
{
Mutex::Autolock _l(mQueueLock);
- // allowLatchUnsignaled acts as a filter condition when latch unsignaled is either auto
- // or always. auto: in this case we let buffer latch unsignaled if we have only one
- // applyToken and if only first transaction is latch unsignaled. If more than one
- // applyToken we don't latch unsignaled.
- bool allowLatchUnsignaled = allowedLatchUnsignaled();
- bool isFirstUnsignaledTransactionApplied = false;
// Collect transactions from pending transaction queue.
auto it = mPendingTransactionQueues.begin();
while (it != mPendingTransactionQueues.end()) {
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
+ if (stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) {
+ break;
+ }
+
auto& transaction = transactionQueue.front();
- if (!transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
- transaction.isAutoTimestamp,
- transaction.desiredPresentTime,
- transaction.originUid, transaction.states,
- bufferLayersReadyToPresent,
- allowLatchUnsignaled)) {
+ const auto ready =
+ transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
+ transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
+ transaction.originUid, transaction.states,
+ bufferLayersReadyToPresent,
+ transactions.size());
+ if (ready == TransactionReadiness::NotReady) {
setTransactionFlags(eTransactionFlushNeeded);
break;
}
transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
bufferLayersReadyToPresent.insert(state.surface);
});
+ const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled);
+ if (appliedUnsignaled) {
+ applyTokensWithUnsignaledTransactions.insert(transaction.applyToken);
+ }
+
transactions.emplace_back(std::move(transaction));
transactionQueue.pop();
- if (allowLatchUnsignaled &&
- enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto) {
- // if allowLatchUnsignaled && we are in LatchUnsignaledConfig::Auto
- // then we should have only one applyToken for processing.
- // so we can stop further transactions on this applyToken.
- isFirstUnsignaledTransactionApplied = true;
- break;
- }
}
if (transactionQueue.empty()) {
@@ -3702,25 +3715,34 @@
// Case 3: others are the transactions that are ready to apply.
while (!mTransactionQueue.empty()) {
auto& transaction = mTransactionQueue.front();
- bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+ const bool pendingTransactions =
+ mPendingTransactionQueues.find(transaction.applyToken) !=
mPendingTransactionQueues.end();
- if (isFirstUnsignaledTransactionApplied || pendingTransactions ||
- !transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
- transaction.isAutoTimestamp,
- transaction.desiredPresentTime,
- transaction.originUid, transaction.states,
- bufferLayersReadyToPresent,
- allowLatchUnsignaled)) {
+ const auto ready = [&]() REQUIRES(mStateLock) {
+ if (pendingTransactions ||
+ stopTransactionProcessing(applyTokensWithUnsignaledTransactions)) {
+ return TransactionReadiness::NotReady;
+ }
+
+ return transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
+ transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
+ transaction.originUid, transaction.states,
+ bufferLayersReadyToPresent,
+ transactions.size());
+ }();
+
+ if (ready == TransactionReadiness::NotReady) {
mPendingTransactionQueues[transaction.applyToken].push(std::move(transaction));
} else {
transaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
bufferLayersReadyToPresent.insert(state.surface);
});
- transactions.emplace_back(std::move(transaction));
- if (allowLatchUnsignaled &&
- enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto) {
- isFirstUnsignaledTransactionApplied = true;
+ const bool appliedUnsignaled = (ready == TransactionReadiness::ReadyUnsignaled);
+ if (appliedUnsignaled) {
+ applyTokensWithUnsignaledTransactions.insert(transaction.applyToken);
}
+ transactions.emplace_back(std::move(transaction));
}
mTransactionQueue.pop_front();
ATRACE_INT("TransactionQueue", mTransactionQueue.size());
@@ -3757,62 +3779,6 @@
return needsTraversal;
}
-bool SurfaceFlinger::allowedLatchUnsignaled() {
- if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
- return false;
- }
- // Always mode matches the current latch unsignaled behavior.
- // This behavior is currently used by the partners and we would like
- // to keep it until we are completely migrated to Auto mode successfully
- // and we we have our fallback based implementation in place.
- if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Always) {
- return true;
- }
-
- // if enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto
- // we don't latch unsignaled if more than one applyToken, as it can backpressure
- // the other transactions.
- if (mPendingTransactionQueues.size() > 1) {
- return false;
- }
- std::optional<sp<IBinder>> applyToken = std::nullopt;
- bool isPendingTransactionQueuesItem = false;
- if (!mPendingTransactionQueues.empty()) {
- applyToken = mPendingTransactionQueues.begin()->first;
- isPendingTransactionQueuesItem = true;
- }
-
- for (const auto& item : mTransactionQueue) {
- if (!applyToken.has_value()) {
- applyToken = item.applyToken;
- } else if (applyToken.has_value() && applyToken != item.applyToken) {
- return false;
- }
- }
-
- if (isPendingTransactionQueuesItem) {
- return checkTransactionCanLatchUnsignaled(
- mPendingTransactionQueues.begin()->second.front());
- } else if (applyToken.has_value()) {
- return checkTransactionCanLatchUnsignaled((mTransactionQueue.front()));
- }
- return false;
-}
-
-bool SurfaceFlinger::checkTransactionCanLatchUnsignaled(const TransactionState& transaction) {
- if (transaction.states.size() == 1) {
- const auto& state = transaction.states.begin()->state;
- if ((state.flags & ~layer_state_t::eBufferChanged) == 0 &&
- state.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
- state.bufferData->acquireFence &&
- state.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ATRACE_NAME("transactionCanLatchUnsignaled");
- return true;
- }
- }
- return false;
-}
-
bool SurfaceFlinger::transactionFlushNeeded() {
Mutex::Autolock _l(mQueueLock);
return !mPendingTransactionQueues.empty() || !mTransactionQueue.empty();
@@ -3839,12 +3805,46 @@
return prediction->presentTime >= expectedPresentTime &&
prediction->presentTime - expectedPresentTime >= earlyLatchVsyncThreshold;
}
+bool SurfaceFlinger::shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t& state,
+ size_t numStates, size_t totalTXapplied) {
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
+ ALOGV("%s: false (LatchUnsignaledConfig::Disabled)", __func__);
+ return false;
+ }
-bool SurfaceFlinger::transactionIsReadyToBeApplied(
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Always) {
+ ALOGV("%s: true (LatchUnsignaledConfig::Always)", __func__);
+ return true;
+ }
+
+ // We only want to latch unsignaled when a single layer is updated in this
+ // transaction (i.e. not a blast sync transaction).
+ if (numStates != 1) {
+ ALOGV("%s: false (numStates=%zu)", __func__, numStates);
+ return false;
+ }
+
+ if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer &&
+ totalTXapplied > 0) {
+ ALOGV("%s: false (LatchUnsignaledConfig::AutoSingleLayer; totalTXapplied=%zu)", __func__,
+ totalTXapplied);
+ return false;
+ }
+
+ if (!layer->simpleBufferUpdate(state)) {
+ ALOGV("%s: false (!simpleBufferUpdate)", __func__);
+ return false;
+ }
+
+ ALOGV("%s: true", __func__);
+ return true;
+}
+
+auto SurfaceFlinger::transactionIsReadyToBeApplied(
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
uid_t originUid, const Vector<ComposerState>& states,
const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
- bool allowLatchUnsignaled) const {
+ size_t totalTXapplied) const -> TransactionReadiness {
ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId);
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
@@ -3852,31 +3852,24 @@
if (!isAutoTimestamp && desiredPresentTime >= expectedPresentTime &&
desiredPresentTime < expectedPresentTime + s2ns(1)) {
ATRACE_NAME("not current");
- return false;
+ return TransactionReadiness::NotReady;
}
if (!mScheduler->isVsyncValid(expectedPresentTime, originUid)) {
ATRACE_NAME("!isVsyncValid");
- return false;
+ return TransactionReadiness::NotReady;
}
// If the client didn't specify desiredPresentTime, use the vsyncId to determine the expected
// present time of this transaction.
if (isAutoTimestamp && frameIsEarly(expectedPresentTime, info.vsyncId)) {
ATRACE_NAME("frameIsEarly");
- return false;
+ return TransactionReadiness::NotReady;
}
+ bool fenceUnsignaled = false;
for (const ComposerState& state : states) {
const layer_state_t& s = state.state;
- const bool acquireFenceChanged = s.bufferData &&
- s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged);
- if (acquireFenceChanged && s.bufferData->acquireFence && !allowLatchUnsignaled &&
- s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ATRACE_NAME("fence unsignaled");
- return false;
- }
-
sp<Layer> layer = nullptr;
if (s.surface) {
layer = fromHandle(s.surface).promote();
@@ -3890,6 +3883,22 @@
ATRACE_NAME(layer->getName().c_str());
+ const bool allowLatchUnsignaled =
+ shouldLatchUnsignaled(layer, s, states.size(), totalTXapplied);
+ ATRACE_INT("allowLatchUnsignaled", allowLatchUnsignaled);
+
+ const bool acquireFenceChanged = s.bufferData &&
+ s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
+ s.bufferData->acquireFence;
+ fenceUnsignaled = fenceUnsignaled ||
+ (acquireFenceChanged &&
+ s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled);
+
+ if (fenceUnsignaled && !allowLatchUnsignaled) {
+ ATRACE_NAME("fence unsignaled");
+ return TransactionReadiness::NotReady;
+ }
+
if (s.hasBufferChanges()) {
// If backpressure is enabled and we already have a buffer to commit, keep the
// transaction in the queue.
@@ -3897,11 +3906,11 @@
bufferLayersReadyToPresent.find(s.surface) != bufferLayersReadyToPresent.end();
if (layer->backpressureEnabled() && hasPendingBuffer && isAutoTimestamp) {
ATRACE_NAME("hasPendingBuffer");
- return false;
+ return TransactionReadiness::NotReady;
}
}
}
- return true;
+ return fenceUnsignaled ? TransactionReadiness::ReadyUnsignaled : TransactionReadiness::Ready;
}
void SurfaceFlinger::queueTransaction(TransactionState& state) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b95cd91..aecd43a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -137,7 +137,20 @@
eTransactionMask = 0x1f,
};
-enum class LatchUnsignaledConfig { Always, Auto, Disabled };
+// Latch Unsignaled buffer behaviours
+enum class LatchUnsignaledConfig {
+ // All buffers are latched signaled.
+ Disabled,
+
+ // Latch unsignaled is permitted when a single layer is updated in a frame,
+ // and the update includes just a buffer update (i.e. no sync transactions
+ // or geometry changes).
+ AutoSingleLayer,
+
+ // All buffers are latched unsignaled. This behaviour is discouraged as it
+ // can break sync transactions, stall the display and cause undesired side effects.
+ Always,
+};
using DisplayColorSetting = compositionengine::OutputColorSetting;
@@ -749,16 +762,21 @@
uint32_t setTransactionFlags(uint32_t mask, TransactionSchedule,
const sp<IBinder>& applyToken = {});
void commitOffscreenLayers();
- bool transactionIsReadyToBeApplied(
+ enum class TransactionReadiness {
+ NotReady,
+ Ready,
+ ReadyUnsignaled,
+ };
+ TransactionReadiness transactionIsReadyToBeApplied(
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
uid_t originUid, const Vector<ComposerState>& states,
const std::unordered_set<sp<IBinder>, SpHash<IBinder>>& bufferLayersReadyToPresent,
- bool allowLatchUnsignaled) const REQUIRES(mStateLock);
+ size_t totalTXapplied) const REQUIRES(mStateLock);
static LatchUnsignaledConfig getLatchUnsignaledConfig();
- bool latchUnsignaledIsAllowed(std::vector<TransactionState>& transactions) REQUIRES(mStateLock);
- bool allowedLatchUnsignaled() REQUIRES(mQueueLock, mStateLock);
- bool checkTransactionCanLatchUnsignaled(const TransactionState& transaction)
- REQUIRES(mStateLock);
+ static bool shouldLatchUnsignaled(const sp<Layer>& layer, const layer_state_t&,
+ size_t numStates, size_t totalTXapplied);
+ bool stopTransactionProcessing(const std::unordered_set<sp<IBinder>, SpHash<IBinder>>&
+ applyTokensWithUnsignaledTransactions) const;
bool applyTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId)
REQUIRES(mStateLock);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index 4f89cd9..30a6fbd 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -25,7 +25,7 @@
static constexpr LatchUnsignaledConfig kLatchUnsignaledConfig[] = {
LatchUnsignaledConfig::Always,
- LatchUnsignaledConfig::Auto,
+ LatchUnsignaledConfig::AutoSingleLayer,
LatchUnsignaledConfig::Disabled,
};
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index ed23176..4683c51 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -72,13 +72,6 @@
EXPECT_CALL(*mVSyncTracker, currentPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
- EXPECT_CALL(*mFenceUnsignaled, getStatus())
- .WillRepeatedly(Return(Fence::Status::Unsignaled));
- EXPECT_CALL(*mFenceUnsignaled2, getStatus())
- .WillRepeatedly(Return(Fence::Status::Unsignaled));
- EXPECT_CALL(*mFenceSignaled, getStatus()).WillRepeatedly(Return(Fence::Status::Signaled));
- EXPECT_CALL(*mFenceSignaled2, getStatus()).WillRepeatedly(Return(Fence::Status::Signaled));
-
mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
@@ -89,10 +82,6 @@
mock::VsyncController* mVsyncController = new mock::VsyncController();
mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker();
- sp<mock::MockFence> mFenceUnsignaled = sp<mock::MockFence>::make();
- sp<mock::MockFence> mFenceSignaled = sp<mock::MockFence>::make();
- sp<mock::MockFence> mFenceUnsignaled2 = sp<mock::MockFence>::make();
- sp<mock::MockFence> mFenceSignaled2 = sp<mock::MockFence>::make();
struct TransactionInfo {
Vector<ComposerState> states;
@@ -129,15 +118,6 @@
transaction.frameTimelineInfo = frameTimelineInfo;
}
- void setupSingleWithComposer(TransactionInfo& transaction, uint32_t flags,
- bool syncInputWindows, int64_t desiredPresentTime,
- bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo,
- const Vector<ComposerState>* states) {
- setupSingle(transaction, flags, syncInputWindows, desiredPresentTime, isAutoTimestamp,
- frameTimelineInfo);
- transaction.states = *states;
- }
-
void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
@@ -263,189 +243,6 @@
EXPECT_EQ(0u, transactionQueue.size());
}
- void Flush_removesUnsignaledFromTheQueue(Vector<ComposerState> state1,
- Vector<ComposerState> state2,
- bool updateApplyToken = true) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
-
- TransactionInfo transactionA;
- setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state1);
-
- mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
- transactionA.displays, transactionA.flags,
- transactionA.applyToken, transactionA.inputWindowCommands,
- transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionA.id);
-
- TransactionInfo transactionB;
- if (updateApplyToken) {
- transactionB.applyToken = sp<IBinder>();
- }
- setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state2);
- mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
- transactionB.displays, transactionB.flags,
- transactionB.applyToken, transactionB.inputWindowCommands,
- transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionB.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(2ul, mFlinger.getTransactionCommittedSignals().size());
- }
-
- void Flush_removesFromTheQueue(const Vector<ComposerState>& state) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
-
- TransactionInfo transaction;
- setupSingleWithComposer(transaction, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state);
-
- mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
- transaction.displays, transaction.flags,
- transaction.applyToken, transaction.inputWindowCommands,
- transaction.desiredPresentTime, transaction.isAutoTimestamp,
- transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transaction.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(1u, mFlinger.getTransactionCommittedSignals().size());
- }
-
- void Flush_keepsInTheQueue(const Vector<ComposerState>& state) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
-
- TransactionInfo transaction;
- setupSingleWithComposer(transaction, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state);
-
- mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
- transaction.displays, transaction.flags,
- transaction.applyToken, transaction.inputWindowCommands,
- transaction.desiredPresentTime, transaction.isAutoTimestamp,
- transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transaction.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(1u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size());
- }
-
- void Flush_KeepsUnsignaledInTheQueue(const Vector<ComposerState>& state1,
- const Vector<ComposerState>& state2,
- bool updateApplyToken = true,
- uint32_t pendingTransactionQueueSize = 1u) {
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- auto time = systemTime();
- TransactionInfo transactionA;
- TransactionInfo transactionB;
- setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state1);
- setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state2);
- mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
- transactionA.displays, transactionA.flags,
- transactionA.applyToken, transactionA.inputWindowCommands,
- transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionA.id);
- if (updateApplyToken) {
- transactionB.applyToken = sp<IBinder>();
- }
- mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
- transactionB.displays, transactionB.flags,
- transactionB.applyToken, transactionB.inputWindowCommands,
- transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionB.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(pendingTransactionQueueSize, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- }
-
- void Flush_removesSignaledFromTheQueue(const Vector<ComposerState>& state1,
- const Vector<ComposerState>& state2) {
- ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
-
- auto time = systemTime();
- TransactionInfo transactionA;
- TransactionInfo transactionB;
- setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state1);
- setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous,
- /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true,
- FrameTimelineInfo{}, &state2);
- mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
- transactionA.displays, transactionA.flags,
- transactionA.applyToken, transactionA.inputWindowCommands,
- transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
- transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionA.id);
- mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
- transactionB.displays, transactionB.flags,
- transactionB.applyToken, transactionB.inputWindowCommands,
- transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
- transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
- transactionB.id);
-
- mFlinger.flushTransactionQueues();
- EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
- EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
- EXPECT_EQ(2ul, mFlinger.getTransactionCommittedSignals().size());
- }
-
- static Vector<ComposerState> createComposerStateVector(const ComposerState& state1,
- const ComposerState& state2) {
- Vector<ComposerState> states;
- states.push_back(state1);
- states.push_back(state2);
- return states;
- }
-
- static Vector<ComposerState> createComposerStateVector(const ComposerState& state) {
- Vector<ComposerState> states;
- states.push_back(state);
- return states;
- }
-
- static ComposerState createComposerState(int layerId, sp<Fence> fence,
- uint32_t stateFlags = layer_state_t::eBufferChanged) {
- ComposerState composer_state;
- composer_state.state.bufferData = std::make_shared<BufferData>();
- composer_state.state.bufferData->acquireFence = std::move(fence);
- composer_state.state.layerId = layerId;
- composer_state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
- composer_state.state.flags = stateFlags;
- return composer_state;
- }
-
bool mHasListenerCallbacks = false;
std::vector<ListenerCallbacks> mCallbacks;
int mTransactionNumber = 0;
@@ -529,215 +326,677 @@
EXPECT_EQ(nullptr, ret.promote().get());
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSingleSignaledFromTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled)));
+class LatchUnsignaledTest : public TransactionApplicationTest {
+public:
+ void TearDown() override {
+ // Clear all transaction queues to release all transactions we sent
+ // in the tests. Otherwise, gmock complains about memory leaks.
+ mFlinger.getTransactionQueue().clear();
+ mFlinger.getPendingTransactionQueue().clear();
+ mFlinger.getTransactionCommittedSignals().clear();
+ mFlinger.commitTransactionsLocked(eTransactionMask);
+ mFlinger.mutableCurrentState().layersSortedByZ.clear();
+ mFlinger.mutableDrawingState().layersSortedByZ.clear();
+ }
+
+ static sp<Fence> fence(Fence::Status status) {
+ const auto fence = sp<mock::MockFence>::make();
+ EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(status));
+ return fence;
+ }
+
+ ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what) {
+ ComposerState state;
+ state.state.bufferData = std::make_shared<BufferData>();
+ state.state.bufferData->acquireFence = std::move(fence);
+ state.state.layerId = layerId;
+ state.state.surface =
+ sp<BufferStateLayer>::make(
+ LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
+ ->getHandle();
+ state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
+
+ state.state.what = what;
+ if (what & layer_state_t::eCropChanged) {
+ state.state.crop = Rect(1, 2, 3, 4);
+ }
+ return state;
+ }
+
+ TransactionInfo createTransactionInfo(const sp<IBinder>& applyToken,
+ const std::vector<ComposerState>& states) {
+ TransactionInfo transaction;
+ const uint32_t kFlags = ISurfaceComposer::eSynchronous;
+ const bool kSyncInputWindows = false;
+ const nsecs_t kDesiredPresentTime = systemTime();
+ const bool kIsAutoTimestamp = true;
+ const auto kFrameTimelineInfo = FrameTimelineInfo{};
+
+ setupSingle(transaction, kFlags, kSyncInputWindows, kDesiredPresentTime, kIsAutoTimestamp,
+ kFrameTimelineInfo);
+ transaction.applyToken = applyToken;
+ for (const auto& state : states) {
+ transaction.states.push_back(state);
+ }
+
+ return transaction;
+ }
+
+ void setTransactionStates(const std::vector<TransactionInfo>& transactions,
+ size_t expectedTransactionsApplied,
+ size_t expectedTransactionsPending) {
+ EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
+ EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
+
+ for (const auto& transaction : transactions) {
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
+ transaction.displays, transaction.flags,
+ transaction.applyToken, transaction.inputWindowCommands,
+ transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, transaction.uncacheBuffer,
+ mHasListenerCallbacks, mCallbacks, transaction.id);
+ }
+ mFlinger.flushTransactionQueues();
+ EXPECT_EQ(0u, mFlinger.getTransactionQueue().size());
+ EXPECT_EQ(expectedTransactionsPending, mFlinger.getPendingTransactionQueue().size());
+ EXPECT_EQ(expectedTransactionsApplied, mFlinger.getTransactionCommittedSignals().size());
+ }
+};
+
+class LatchUnsignaledAutoSingleLayerTest : public LatchUnsignaledTest {
+public:
+ void SetUp() override {
+ LatchUnsignaledTest::SetUp();
+ SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::AutoSingleLayer;
+ }
+};
+
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSingleUnSignaledFromTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleUnSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled, layer_state_t::eCropChanged)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eCropChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled,
- layer_state_t::eCropChanged | layer_state_t::eBufferChanged)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eCropChanged |
+ layer_state_t::
+ eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsInTheQueueSameApplyTokenMultiState_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 1, mFenceSignaled)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueueSameApplyTokenMultiState) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueue_MultipleStateTransaction_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 2, mFenceSignaled)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueue_MultipleStateTransaction) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_removesSignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled2)));
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemoveSignaledWithUnsignaledIntact_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)));
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemoveSignaledWithUnsignaledIntact) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepsTransactionInTheQueueSameApplyToken_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled)),
- /*updateApplyToken*/ false);
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsTransactionInTheQueue_LatchUnsignaled_Auto) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)),
- /*updateApplyToken*/ true,
- /*pendingTransactionQueueSize*/ 2u);
- EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueue) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsApplied, kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled)));
+class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
+public:
+ void SetUp() override {
+ LatchUnsignaledTest::SetUp();
+ SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
+ }
+};
+
+TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueue_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueueSameLayerId_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueSameLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueueDifferentLayerId_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_keepsInTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueDifferentLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnSignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_removesSignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled2)));
+TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue_MultipleLayers) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_KeepInTheQueueDifferentApplyToken_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled)));
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueDifferentApplyToken) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepInTheQueueSameApplyToken_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)),
- /*updateApplyToken*/ false);
- EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueSameApplyToken) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_KeepInTheUnsignaledTheQueue_LatchUnsignaled_Disabled) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
- Flush_KeepsUnsignaledInTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceUnsignaled)),
- /*updateApplyToken*/ false);
- EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size());
+TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheUnsignaledTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 0u;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsApplied, kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled)));
+class LatchUnsignaledAlwaysTest : public LatchUnsignaledTest {
+public:
+ void SetUp() override {
+ LatchUnsignaledTest::SetUp();
+ SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
+ }
+};
+
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesSignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesFromTheQueue_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueue) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesFromTheQueueSameLayerId_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 1, mFenceSignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueueSameLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId = 1;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_RemovesFromTheQueueDifferentLayerId_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesFromTheQueue(
- createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled),
- createComposerState(/*layerId*/ 2, mFenceSignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueueDifferentLayerId) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 1u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto mixedTransaction =
+ createTransactionInfo(kApplyToken,
+ {createComposerState(kLayerId1, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ createComposerState(kLayerId2, fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged)});
+ setTransactionStates({mixedTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnSignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesSignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled2)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesSignaledFromTheQueue_MultipleLayers) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_RemovesFromTheQueueDifferentApplyToken_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesUnsignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1, mFenceSignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2,
- mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesFromTheQueueDifferentApplyToken) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({signaledTransaction, unsignaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest,
- Flush_RemovesUnsignaledFromTheQueueSameApplyToken_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesUnsignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1,
- mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2, mFenceSignaled)),
- /*updateApplyToken*/ false);
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesUnsignaledFromTheQueueSameApplyToken) {
+ const sp<IBinder> kApplyToken =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, signaledTransaction}, kExpectedTransactionsApplied,
+ kExpectedTransactionsPending);
}
-TEST_F(TransactionApplicationTest, Flush_RemovesUnsignaledFromTheQueue_LatchUnsignaled_Always) {
- SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always;
- Flush_removesUnsignaledFromTheQueue(createComposerStateVector(
- createComposerState(/*layerId*/ 1,
- mFenceUnsignaled)),
- createComposerStateVector(
- createComposerState(/*layerId*/ 2,
- mFenceUnsignaled)));
+TEST_F(LatchUnsignaledAlwaysTest, Flush_RemovesUnsignaledFromTheQueue) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsApplied = 2u;
+ const auto kExpectedTransactionsPending = 0u;
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsApplied, kExpectedTransactionsPending);
}
} // namespace android