sde: Add support for virtual and external display concurrency
Wait for virtual display to tear down before continuing with
external display connection.
Change-Id: I7f30d51575d6e3e671738f91f495a0c1c6730311
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 2201aa6..450565e 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -240,10 +240,13 @@
}
break;
case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_external_) {
+ break;
+ }
if (hwc_session->ValidateContentList(content_list)) {
- hwc_session->CreateVirtualDisplay(hwc_session, content_list);
+ hwc_session->CreateVirtualDisplay(content_list);
} else {
- hwc_session->DestroyVirtualDisplay(hwc_session);
+ hwc_session->DestroyVirtualDisplay();
}
if (hwc_session->display_virtual_) {
@@ -284,6 +287,21 @@
}
break;
case HWC_DISPLAY_VIRTUAL:
+ if (hwc_session->display_external_) {
+ if (content_list) {
+ for (size_t i = 0; i < content_list->numHwLayers; i++) {
+ if (content_list->hwLayers[i].acquireFenceFd >= 0) {
+ close(content_list->hwLayers[i].acquireFenceFd);
+ content_list->hwLayers[i].acquireFenceFd = -1;
+ }
+ }
+ if (content_list->outbufAcquireFenceFd >= 0) {
+ close(content_list->outbufAcquireFenceFd);
+ content_list->outbufAcquireFenceFd = -1;
+ }
+ content_list->retireFenceFd = -1;
+ }
+ }
if (hwc_session->display_virtual_) {
hwc_session->display_virtual_->Commit(content_list);
}
@@ -514,49 +532,49 @@
return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
}
-int HWCSession::CreateVirtualDisplay(HWCSession *hwc_session,
- hwc_display_contents_1_t *content_list) {
+int HWCSession::CreateVirtualDisplay(hwc_display_contents_1_t *content_list) {
int status = 0;
- if (!hwc_session->display_virtual_) {
+ if (!display_virtual_) {
// Create virtual display device
- hwc_session->display_virtual_ = new HWCDisplayVirtual(hwc_session->core_intf_,
- &hwc_session->hwc_procs_);
- if (!hwc_session->display_virtual_) {
+ display_virtual_ = new HWCDisplayVirtual(core_intf_, &hwc_procs_);
+ if (!display_virtual_) {
// This is not catastrophic. Leave a warning message for now.
DLOGW("Virtual Display creation failed");
return -ENOMEM;
}
- status = hwc_session->display_virtual_->Init();
+ status = display_virtual_->Init();
if (status) {
goto CleanupOnError;
}
- status = hwc_session->display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+ status = display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
if (status) {
goto CleanupOnError;
}
}
- if (hwc_session->display_virtual_) {
- status = hwc_session->display_virtual_->SetActiveConfig(content_list);
+ if (display_virtual_) {
+ status = display_virtual_->SetActiveConfig(content_list);
}
return status;
CleanupOnError:
- return hwc_session->DestroyVirtualDisplay(hwc_session);
+ return DestroyVirtualDisplay();
}
-int HWCSession::DestroyVirtualDisplay(HWCSession *hwc_session) {
+int HWCSession::DestroyVirtualDisplay() {
int status = 0;
- if (hwc_session->display_virtual_) {
- status = hwc_session->display_virtual_->Deinit();
+ if (display_virtual_) {
+ status = display_virtual_->Deinit();
if (!status) {
- delete hwc_session->display_virtual_;
- hwc_session->display_virtual_ = NULL;
+ delete display_virtual_;
+ display_virtual_ = NULL;
+ // Signal the HotPlug thread to continue with the external display connection
+ locker_.Signal();
}
}
@@ -808,6 +826,14 @@
if (connected) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+ if (display_virtual_) {
+ // Wait for the virtual display to tear down
+ int status = locker_.WaitFinite(kExternalConnectionTimeoutMs);
+ if (status != 0) {
+ DLOGE("Timed out while waiting for virtual display to tear down.");
+ return -1;
+ }
+ }
if (display_external_) {
DLOGE("HDMI already connected");
return -1;
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index dffa864..54ab852 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -49,6 +49,8 @@
int Deinit();
private:
+ static const int kExternalConnectionTimeoutMs = 500;
+
// hwc methods
static int Open(const hw_module_t *module, const char* name, hw_device_t **device);
static int Close(hw_device_t *device);
@@ -75,8 +77,8 @@
int HotPlugHandler(bool connected);
void ResetPanel();
bool ValidateContentList(hwc_display_contents_1_t *content_list);
- int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
- int DestroyVirtualDisplay(HWCSession *hwc_session);
+ int CreateVirtualDisplay(hwc_display_contents_1_t *content_list);
+ int DestroyVirtualDisplay();
// CoreEventHandler methods
virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);