SF: Update display properties on hotplug connect
When a hotplug connect event for already connected display
is received, destroy and recreate the display device in SF,
then send a "hotplug connect" event to Display manager. This
way display properties will be updated.
Bug: 143451809
Test: atest libsurfaceflinger_unittest
Test: atest SurfaceFligner_test
Test: atest CompositionTest
Test: Manually on device:
2. adb shell dumpsys display
3. unplug primary display
4. plug another display
5. adb shell dumpsys display
Test: Manually on device:
1. disconnect and reconnect display
2. power off and on the screen
3. make sure the device didn't crash
Merged-In: I89996d9340f6570fa5ae0cc0977eaba7a2d3693c
Change-Id: I89996d9340f6570fa5ae0cc0977eaba7a2d3693c
(cherry picked from commit 700e639f7d283987fb7b994a038dc0ca5dba3dbf)
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2da92b3..34d6d31 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2385,7 +2385,8 @@
}
DisplayDeviceState state;
- state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId)};
+ state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId),
+ event.hwcDisplayId};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = info->name;
@@ -2394,6 +2395,12 @@
mPhysicalDisplayTokens.emplace(displayId, std::move(token));
mInterceptor->saveDisplayCreation(state);
+ } else {
+ ALOGV("Recreating display %s", to_string(displayId).c_str());
+
+ const auto token = it->second;
+ auto& state = mCurrentState.displays.editValueFor(token);
+ state.sequenceId = DisplayDeviceState{}.sequenceId;
}
} else {
ALOGV("Removing display %s", to_string(displayId).c_str());
@@ -2571,20 +2578,17 @@
producer = bqProducer;
}
- if (displaySurface != nullptr) {
- mDisplays.emplace(displayToken,
- setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
- displaySurface, producer));
- if (!state.isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, true);
- }
+ LOG_FATAL_IF(!displaySurface);
+ const auto display = setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
+ displaySurface, producer);
+ mDisplays.emplace(displayToken, display);
+ if (!state.isVirtual()) {
+ LOG_FATAL_IF(!displayId);
+ dispatchDisplayHotplugEvent(displayId->value, true);
+ }
- const auto displayDevice = mDisplays[displayToken];
- if (displayDevice->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() *
- displayDevice->getHeight());
- }
+ if (display->isPrimary()) {
+ mScheduler->onPrimaryDisplayAreaChanged(display->getWidth() * display->getHeight());
}
}
@@ -2595,7 +2599,7 @@
display->disconnect();
if (!display->isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
+ LOG_FATAL_IF(!displayId);
dispatchDisplayHotplugEvent(displayId->value, false);
}
}
@@ -2608,13 +2612,19 @@
const DisplayDeviceState& drawingState) {
const sp<IBinder> currentBinder = IInterface::asBinder(currentState.surface);
const sp<IBinder> drawingBinder = IInterface::asBinder(drawingState.surface);
- if (currentBinder != drawingBinder) {
+ if (currentBinder != drawingBinder || currentState.sequenceId != drawingState.sequenceId) {
// changing the surface is like destroying and recreating the DisplayDevice
if (const auto display = getDisplayDeviceLocked(displayToken)) {
display->disconnect();
}
mDisplays.erase(displayToken);
+ if (const auto& physical = currentState.physical) {
+ getHwComposer().allocatePhysicalDisplay(physical->hwcDisplayId, physical->id);
+ }
processDisplayAdded(displayToken, currentState);
+ if (currentState.physical) {
+ initializeDisplays();
+ }
return;
}