Determine displayType in SurfaceFlinger
This change eliminates an assumption that the first hotplug connect
event is for the primary display, and all other events are for the
external display.
Bug: 38464421
Test: Boots, settings app navigable
Change-Id: I753deb9a4e99a7b225ab89562c7acf4ce284dbf5
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index affe505..070b691 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -52,24 +52,13 @@
class ComposerCallbackBridge : public Hwc2::IComposerCallback {
public:
ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
- : mCallback(callback), mSequenceId(sequenceId),
- mHasPrimaryDisplay(false) {}
+ : mCallback(callback), mSequenceId(sequenceId) {}
Return<void> onHotplug(Hwc2::Display display,
IComposerCallback::Connection conn) override
{
HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
- if (!mHasPrimaryDisplay) {
- LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected,
- "Initial onHotplug callback should be "
- "primary display connected");
- mHasPrimaryDisplay = true;
- mCallback->onHotplugReceived(mSequenceId, display,
- connection, true);
- } else {
- mCallback->onHotplugReceived(mSequenceId, display,
- connection, false);
- }
+ mCallback->onHotplugReceived(mSequenceId, display, connection);
return Void();
}
@@ -85,12 +74,9 @@
return Void();
}
- bool HasPrimaryDisplay() { return mHasPrimaryDisplay; }
-
private:
ComposerCallback* mCallback;
int32_t mSequenceId;
- bool mHasPrimaryDisplay;
};
} // namespace anonymous
@@ -117,8 +103,6 @@
sp<ComposerCallbackBridge> callbackBridge(
new ComposerCallbackBridge(callback, sequenceId));
mComposer->registerCallback(callbackBridge);
- LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(),
- "Registered composer callback but didn't get primary display");
}
// Required by HWC2 device
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index a15c6d9..7b98b3e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -65,8 +65,7 @@
class ComposerCallback {
public:
virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
- Connection connection,
- bool primaryDisplay) = 0;
+ Connection connection) = 0;
virtual void onRefreshReceived(int32_t sequenceId,
hwc2_display_t display) = 0;
virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c0f8f96..1677b07 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -119,23 +119,22 @@
}
}
-void HWComposer::onHotplug(hwc2_display_t displayId,
+void HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType,
HWC2::Connection connection) {
- ALOGV("hotplug: %" PRIu64 ", %s", displayId,
+ if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ ALOGE("Invalid display type of %d", displayType);
+ return;
+ }
+
+ ALOGV("hotplug: %" PRIu64 ", %s %s", displayId,
+ displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
to_string(connection).c_str());
mHwcDevice->onHotplug(displayId, connection);
- if (!mDisplayData[0].hwcDisplay) {
- ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary"
- " display would be connected");
- mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId);
- mHwcDisplaySlots[displayId] = 0;
- } else {
- // Disconnect is handled through HWComposer::disconnectDisplay via
- // SurfaceFlinger's onHotplugReceived callback handling
- if (connection == HWC2::Connection::Connected) {
- mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId);
- mHwcDisplaySlots[displayId] = 1;
- }
+ // Disconnect is handled through HWComposer::disconnectDisplay via
+ // SurfaceFlinger's onHotplugReceived callback handling
+ if (connection == HWC2::Connection::Connected) {
+ mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+ mHwcDisplaySlots[displayId] = displayType;
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 74b3a38..ee0a725 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -136,7 +136,7 @@
// DisplayDevice::DisplayType of the display is returned as an output param.
bool onVsync(hwc2_display_t displayId, int64_t timestamp,
int32_t* outDisplay);
- void onHotplug(hwc2_display_t displayId, HWC2::Connection connection);
+ void onHotplug(hwc2_display_t displayId, int32_t displayType, HWC2::Connection connection);
void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 707a0de..3145ac3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1263,14 +1263,10 @@
*compositorTiming = getBE().mCompositorTiming;
}
-void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
- hwc2_display_t display, HWC2::Connection connection,
- bool primaryDisplay) {
- ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
- sequenceId, display,
- connection == HWC2::Connection::Connected ?
- "connected" : "disconnected",
- primaryDisplay ? "primary" : "external");
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+ HWC2::Connection connection) {
+ ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display,
+ connection == HWC2::Connection::Connected ? "connected" : "disconnected");
// Ignore events that do not have the right sequenceId.
if (sequenceId != getBE().mComposerSequenceId) {
@@ -1283,7 +1279,7 @@
// acquire it here.
ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
- mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection, primaryDisplay});
+ mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection});
setTransactionFlags(eDisplayTransactionNeeded);
}
@@ -2044,17 +2040,46 @@
// here the transaction has been committed
}
+DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display,
+ HWC2::Connection connection) const {
+ // Figure out whether the event is for the primary display or an
+ // external display by matching the Hwc display id against one for a
+ // connected display. If we did not find a match, we then check what
+ // displays are not already connected to determine the type. If we don't
+ // have a connected primary display, we assume the new display is meant to
+ // be the primary display, and then if we don't have an external display,
+ // we assume it is that.
+ const auto primaryDisplayId =
+ getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY);
+ const auto externalDisplayId =
+ getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL);
+ if (primaryDisplayId && primaryDisplayId == display) {
+ return DisplayDevice::DISPLAY_PRIMARY;
+ } else if (externalDisplayId && externalDisplayId == display) {
+ return DisplayDevice::DISPLAY_EXTERNAL;
+ } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) {
+ return DisplayDevice::DISPLAY_PRIMARY;
+ } else if (connection == HWC2::Connection::Connected && !externalDisplayId) {
+ return DisplayDevice::DISPLAY_EXTERNAL;
+ }
+
+ return DisplayDevice::DISPLAY_ID_INVALID;
+}
+
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
for (const auto& event : mPendingHotplugEvents) {
- DisplayDevice::DisplayType displayType = event.isPrimaryDisplay ?
- DisplayDevice::DISPLAY_PRIMARY : DisplayDevice::DISPLAY_EXTERNAL;
+ auto displayType = determineDisplayType(event.display, event.connection);
+ if (displayType == DisplayDevice::DISPLAY_ID_INVALID) {
+ ALOGW("Unable to determine the display type for display %" PRIu64, event.display);
+ continue;
+ }
if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) {
ALOGE("External displays are not supported by the vr hardware composer.");
continue;
}
- getBE().mHwc->onHotplug(event.display, event.connection);
+ getBE().mHwc->onHotplug(event.display, displayType, event.connection);
if (event.connection == HWC2::Connection::Connected) {
ALOGV("Creating built in display %d", displayType);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 921bb45..a18be9b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -417,8 +417,7 @@
void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
int64_t timestamp) override;
void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
- HWC2::Connection connection,
- bool primaryDisplay) override;
+ HWC2::Connection connection) override;
void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
/* ------------------------------------------------------------------------
@@ -631,6 +630,8 @@
/* ------------------------------------------------------------------------
* Display management
*/
+ DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display,
+ HWC2::Connection connection) const;
void processDisplayChangesLocked();
void processDisplayHotplugEventsLocked();
@@ -737,7 +738,6 @@
struct HotplugEvent {
hwc2_display_t display;
HWC2::Connection connection = HWC2::Connection::Invalid;
- bool isPrimaryDisplay;
};
// protected by mStateLock
std::vector<HotplugEvent> mPendingHotplugEvents;