[sf] Fix latch unsignaled issues
With LatchUnsignaledConfig::AutoSingleLayer flag, we should only
apply a transaction with an unsignaled fence if its the only transaction.
If we pass an unsignaled fence to HWC, HWC might miss presenting
the frame if the fence does not fire in time. If we apply another
transaction we may penalize the other transaction unfairly.
With LatchUnsignaledConfig::Always flag, respect backpressure flag
and take the opportunity to simplify the logic by treating the flag as
a signal to ignore the fence when applying transactions.
Test: surfaceflinger unit tests
Bug: 276229937
Change-Id: Ib5cd8205d62fdf8912b7f5c2cad312a01cae4300
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index d4e2357..03c4e71 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -294,7 +294,8 @@
return fence;
}
- ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what) {
+ ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what,
+ std::optional<sp<IBinder>> layerHandle = std::nullopt) {
ComposerState state;
state.state.bufferData =
std::make_shared<fake::BufferData>(/* bufferId */ 123L, /* width */ 1,
@@ -302,15 +303,20 @@
/* outUsage */ 0);
state.state.bufferData->acquireFence = std::move(fence);
state.state.layerId = layerId;
- state.state.surface =
+ state.state.surface = layerHandle.value_or(
sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
- ->getHandle();
+ ->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);
}
+ if (what & layer_state_t::eFlagsChanged) {
+ state.state.flags = layer_state_t::eEnableBackpressure;
+ state.state.mask = layer_state_t::eEnableBackpressure;
+ }
+
return state;
}
@@ -601,6 +607,41 @@
setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
}
+TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kLayerId2 = 2;
+ const auto kExpectedTransactionsPending = 1u;
+
+ const auto signaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto signaledTransaction2 =
+ createTransactionInfo(kApplyToken2,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Signaled),
+ layer_state_t::eBufferChanged),
+ });
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken3,
+ {
+ createComposerState(kLayerId2,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged),
+ });
+
+ setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction},
+ kExpectedTransactionsPending);
+}
+
class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
public:
void SetUp() override {
@@ -943,6 +984,43 @@
kExpectedTransactionsPending);
}
+TEST_F(LatchUnsignaledAlwaysTest, RespectsBackPressureFlag) {
+ const sp<IBinder> kApplyToken1 =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
+ const auto kLayerId1 = 1;
+ const auto kExpectedTransactionsPending = 1u;
+ auto layer =
+ sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}));
+ auto layerHandle = layer->getHandle();
+ const auto setBackPressureFlagTransaction =
+ createTransactionInfo(kApplyToken1,
+ {createComposerState(kLayerId1, fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged |
+ layer_state_t::eFlagsChanged,
+ {layerHandle})});
+ setTransactionStates({setBackPressureFlagTransaction}, 0u);
+
+ const auto unsignaledTransaction =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged,
+ {layerHandle}),
+ });
+ const auto unsignaledTransaction2 =
+ createTransactionInfo(kApplyToken1,
+ {
+ createComposerState(kLayerId1,
+ fence(Fence::Status::Unsignaled),
+ layer_state_t::eBufferChanged,
+ {layerHandle}),
+ });
+ setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
+ kExpectedTransactionsPending);
+}
+
TEST_F(LatchUnsignaledAlwaysTest, LatchUnsignaledWhenEarlyOffset) {
const sp<IBinder> kApplyToken =
IInterface::asBinder(TransactionCompletedListener::getIInstance());