SF: Manage many-to-one DisplayDevice to layerStack mapping for input
When there is more than one DisplayDevice that is mapped to a
layerStack, we let the display that is configured to receive input take
precedence.
We log an error if there is more than one DisplayDevice that receives
input that is mapped to a layerStack.
Bug: 210779136
Test: atest libguitest
Change-Id: I1d4f3f5fab7c71e8a44e3142404dc91051312698
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8046798..172f73f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3100,41 +3100,61 @@
void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
std::vector<DisplayInfo>& outDisplayInfos) {
- std::unordered_map<uint32_t /*layerStackId*/,
- std::pair<bool /* isSecure */, const ui::Transform>>
- inputDisplayDetails;
+ struct Details {
+ Details(bool receivesInput, bool isSecure, const ui::Transform& transform,
+ const DisplayInfo& info)
+ : receivesInput(receivesInput),
+ isSecure(isSecure),
+ transform(std::move(transform)),
+ info(std::move(info)) {}
+ bool receivesInput;
+ bool isSecure;
+ ui::Transform transform;
+ DisplayInfo info;
+ };
+ std::unordered_map<uint32_t /*layerStackId*/, Details> inputDisplayDetails;
for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
- if (!display->receivesInput()) {
- continue;
- }
const uint32_t layerStackId = display->getLayerStack().id;
const auto& [info, transform] = display->getInputInfo();
const auto& [it, emplaced] =
- inputDisplayDetails.try_emplace(layerStackId, display->isSecure(), transform);
- if (!emplaced) {
- ALOGE("Multiple displays claim to accept input for the same layer stack: %u",
- layerStackId);
+ inputDisplayDetails.try_emplace(layerStackId, display->receivesInput(),
+ display->isSecure(), transform, info);
+ if (emplaced) {
continue;
}
- outDisplayInfos.emplace_back(info);
+
+ // There is more than one display for the layerStack. In this case, the display that is
+ // configured to receive input takes precedence.
+ auto& details = it->second;
+ if (!display->receivesInput()) {
+ continue;
+ }
+ ALOGE_IF(details.receivesInput,
+ "Multiple displays claim to accept input for the same layer stack: %u",
+ layerStackId);
+ details.receivesInput = display->receivesInput();
+ details.isSecure = display->isSecure();
+ details.transform = std::move(transform);
+ details.info = std::move(info);
}
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
- bool isSecure = true;
- ui::Transform displayTransform = ui::Transform();
-
const uint32_t layerStackId = layer->getLayerStack().id;
const auto it = inputDisplayDetails.find(layerStackId);
- if (it != inputDisplayDetails.end()) {
- const auto& [secure, transform] = it->second;
- isSecure = secure;
- displayTransform = transform;
+ if (it == inputDisplayDetails.end()) {
+ // Do not create WindowInfos for windows on displays that cannot receive input.
+ return;
}
- outWindowInfos.push_back(layer->fillInputInfo(displayTransform, isSecure));
+ const auto& details = it->second;
+ outWindowInfos.push_back(layer->fillInputInfo(details.transform, details.isSecure));
});
+
+ for (const auto& [_, details] : inputDisplayDetails) {
+ outDisplayInfos.push_back(std::move(details.info));
+ }
}
void SurfaceFlinger::updateCursorAsync() {