SF: Reject hotplugs on invalid or duplicate ports
When a HWC returns an invalid or duplicate port that collides with an
existing active port, the end result is display identification confusion
in higher layers of the stack. This is especially bad when the confusion
is with the internal/primary display and causes it to malfunction.
Reject hotplugs in which the reported port from HWC is already active.
Flag: EXEMPT bugfix
Bug: 383430671
Test: Display{Id | Identification}Test && libsurfaceflinger_unittest
Change-Id: Id3569ef1d973f4ace51d14c7e3cc9aef17630b22
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6384fcc..0d0246f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3718,6 +3718,7 @@
if (const auto displayOpt = mPhysicalDisplays.get(displayId)) {
const auto& display = displayOpt->get();
const auto& snapshot = display.snapshot();
+ const uint8_t port = snapshot.port();
std::optional<DeviceProductInfo> deviceProductInfo;
if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) {
@@ -3729,14 +3730,14 @@
// Use the cached port via snapshot because we are updating an existing
// display on reconnect.
const auto it =
- mPhysicalDisplays.try_replace(displayId, display.token(), displayId,
- snapshot.port(), snapshot.connectionType(),
- std::move(displayModes), std::move(colorModes),
- std::move(deviceProductInfo));
+ mPhysicalDisplays.try_replace(displayId, display.token(), displayId, port,
+ snapshot.connectionType(), std::move(displayModes),
+ std::move(colorModes), std::move(deviceProductInfo));
auto& state = mCurrentState.displays.editValueFor(it->second.token());
state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId.
state.physical->activeMode = std::move(activeMode);
+ state.physical->port = port;
ALOGI("Reconnecting %s", displayString);
return activeModeId;
}
@@ -3752,6 +3753,7 @@
DisplayDeviceState state;
state.physical = {.id = displayId,
.hwcDisplayId = hwcDisplayId,
+ .port = info.port,
.activeMode = std::move(activeMode)};
if (mIsHdcpViaNegVsync) {
state.isSecure = connectionType == ui::DisplayConnectionType::Internal;
@@ -4067,7 +4069,7 @@
if (const auto& physical = currentState.physical) {
getHwComposer().allocatePhysicalDisplay(physical->hwcDisplayId, physical->id,
- /*physicalSize=*/std::nullopt);
+ physical->port, /*physicalSize=*/std::nullopt);
}
processDisplayAdded(displayToken, currentState);