Skip invisible windows in input list
To reduce traffic sent over binder and the number of copied objects in native code, we decide to remove windows from WindowInfosListener that are not visible because input doesn't need to know about the windows that aren't visible, and invisible windows don't affect the operation of other windows.
Fixes: 305254099
Test: adb shell su root dumpsys SurfaceFlinger
Test: atest LayerSnapshotTest
Flag: EXEMPT bugfix
Change-Id: I1ccc29565ee92277a703d16c07fd1141d6df6862
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 7569c1b..4d9a9ca 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -261,20 +261,25 @@
}
snapshot.isVisible = visible;
- // TODO(b/238781169) we are ignoring this compat for now, since we will have
- // to remove any optimization based on visibility.
+ if (FlagManager::getInstance().skip_invisible_windows_in_input()) {
+ snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visible);
+ } else {
+ // TODO(b/238781169) we are ignoring this compat for now, since we will have
+ // to remove any optimization based on visibility.
- // For compatibility reasons we let layers which can receive input
- // receive input before they have actually submitted a buffer. Because
- // of this we use canReceiveInput instead of isVisible to check the
- // policy-visibility, ignoring the buffer state. However for layers with
- // hasInputInfo()==false we can use the real visibility state.
- // We are just using these layers for occlusion detection in
- // InputDispatcher, and obviously if they aren't visible they can't occlude
- // anything.
- const bool visibleForInput =
- snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
- snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
+ // For compatibility reasons we let layers which can receive input
+ // receive input before they have actually submitted a buffer. Because
+ // of this we use canReceiveInput instead of isVisible to check the
+ // policy-visibility, ignoring the buffer state. However for layers with
+ // hasInputInfo()==false we can use the real visibility state.
+ // We are just using these layers for occlusion detection in
+ // InputDispatcher, and obviously if they aren't visible they can't occlude
+ // anything.
+ const bool visibleForInput =
+ snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
+ snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE,
+ !visibleForInput);
+ }
LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
snapshot.getDebugString().c_str());
}
@@ -1260,6 +1265,10 @@
for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
if (!snapshot.hasInputInfo()) continue;
+ if (FlagManager::getInstance().skip_invisible_windows_in_input() &&
+ snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE)) {
+ continue;
+ }
visitor(snapshot);
}
}
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 12616e3..169fef9 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -159,6 +159,7 @@
DUMP_READ_ONLY_FLAG(display_config_error_hal);
DUMP_READ_ONLY_FLAG(connected_display_hdr);
DUMP_READ_ONLY_FLAG(deprecate_frame_tracker);
+ DUMP_READ_ONLY_FLAG(skip_invisible_windows_in_input);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -266,6 +267,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(display_config_error_hal, "");
FLAG_MANAGER_READ_ONLY_FLAG(connected_display_hdr, "");
FLAG_MANAGER_READ_ONLY_FLAG(deprecate_frame_tracker, "");
+FLAG_MANAGER_READ_ONLY_FLAG(skip_invisible_windows_in_input, "");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index f5bea72..5243596 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -97,6 +97,7 @@
bool display_config_error_hal() const;
bool connected_display_hdr() const;
bool deprecate_frame_tracker() const;
+ bool skip_invisible_windows_in_input() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 014c736..6903941 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -196,6 +196,17 @@
} # single_hop_screenshot
flag {
+ name: "skip_invisible_windows_in_input"
+ namespace: "window_surfaces"
+ description: "Only send visible windows to input list"
+ bug: "305254099"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ } # skip_invisible_windows_in_input
+
+flag {
name: "true_hdr_screenshots"
namespace: "core_graphics"
description: "Enables screenshotting display content in HDR, sans tone mapping"
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index e6b8a26..06518fb 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1551,6 +1551,9 @@
}
TEST_F(LayerSnapshotTest, NonVisibleLayerWithInput) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
+ skip_invisible_windows_in_input,
+ false);
LayerHierarchyTestBase::createRootLayer(3);
setColor(3, {-1._hf, -1._hf, -1._hf});
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
@@ -1576,6 +1579,39 @@
EXPECT_TRUE(foundInputLayer);
}
+TEST_F(LayerSnapshotTest, NonVisibleLayerWithInputShouldNotBeIncluded) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
+ skip_invisible_windows_in_input,
+ true);
+ LayerHierarchyTestBase::createRootLayer(3);
+ setColor(3, {-1._hf, -1._hf, -1._hf});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
+ transactions.back().states.front().layerId = 3;
+ transactions.back().states.front().state.windowInfoHandle = sp<gui::WindowInfoHandle>::make();
+ auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
+ inputInfo->token = sp<BBinder>::make();
+ hideLayer(3);
+ mLifecycleManager.applyTransactions(transactions);
+
+ update(mSnapshotBuilder);
+
+ bool foundInputLayer = false;
+ mSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) {
+ if (snapshot.uniqueSequence == 3) {
+ EXPECT_TRUE(
+ snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE));
+ EXPECT_FALSE(snapshot.isVisible);
+ foundInputLayer = true;
+ }
+ });
+ EXPECT_FALSE(foundInputLayer);
+}
+
TEST_F(LayerSnapshotTest, ForEachSnapshotsWithPredicate) {
std::vector<uint32_t> visitedUniqueSequences;
mSnapshotBuilder.forEachSnapshot(