EDID support for external display hotplug
The hardware_composer caches the edid when a new hotplug event fires
(connected and disconnected). The display services uses this cached edid
when the edid is requested.
Bug: 141007548
Test: Manual, ran on mtp device with wave optics plugged in and
unplugged and verified edid with: "adb shell dumpsys SurfaceFlinger --display-id"
Change-Id: I4556e1d8a3f8677b1d9301d9afbc40d514c86e27
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 5a9360c..582fed3 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -18,6 +18,8 @@
#include <private/dvr/trusted_uids.h>
#include <private/dvr/types.h>
+#include "DisplayHardware/DisplayIdentification.h"
+
using android::dvr::display::DisplayProtocol;
using android::pdx::Channel;
using android::pdx::ErrorStatus;
@@ -44,19 +46,6 @@
Endpoint::Create(display::DisplayProtocol::kClientPath)) {
hardware_composer_.Initialize(
hidl, primary_display_id, request_display_callback);
-
- uint8_t port;
- const auto error = hidl->getDisplayIdentificationData(
- primary_display_id, &display_identification_port_,
- &display_identification_data_);
- if (error != android::hardware::graphics::composer::V2_1::Error::NONE) {
- if (error !=
- android::hardware::graphics::composer::V2_1::Error::UNSUPPORTED) {
- ALOGI("DisplayService: identification data error\n");
- } else {
- ALOGI("DisplayService: identification data unsupported\n");
- }
- }
}
bool DisplayService::IsInitialized() const {
@@ -212,6 +201,7 @@
pdx::Status<std::string> DisplayService::OnGetConfigurationData(
pdx::Message& /*message*/, display::ConfigFileType config_type) {
std::string property_name;
+ DisplayIdentificationData display_identification_data;
switch (config_type) {
case display::ConfigFileType::kLensMetrics:
property_name = kDvrLensMetricsProperty;
@@ -223,11 +213,13 @@
property_name = kDvrDeviceConfigProperty;
break;
case display::ConfigFileType::kDeviceEdid:
- if (display_identification_data_.size() == 0) {
+ display_identification_data =
+ hardware_composer_.GetCurrentDisplayIdentificationData();
+ if (display_identification_data.size() == 0) {
return ErrorStatus(ENOENT);
}
- return std::string(display_identification_data_.begin(),
- display_identification_data_.end());
+ return std::string(display_identification_data.begin(),
+ display_identification_data.end());
default:
return ErrorStatus(EINVAL);
}
@@ -246,7 +238,7 @@
pdx::Status<uint8_t> DisplayService::OnGetDisplayIdentificationPort(
pdx::Message& /*message*/) {
- return display_identification_port_;
+ return hardware_composer_.GetCurrentDisplayPort();
}
// Creates a new DisplaySurface and associates it with this channel. This may
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 06ba566..89f1eae 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -18,8 +18,6 @@
#include "epoll_event_dispatcher.h"
#include "hardware_composer.h"
-#include "DisplayHardware/DisplayIdentification.h"
-
namespace android {
namespace dvr {
@@ -120,9 +118,6 @@
DisplayService(const DisplayService&) = delete;
void operator=(const DisplayService&) = delete;
-
- DisplayIdentificationData display_identification_data_;
- uint8_t display_identification_port_;
};
} // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 9072d89..67607af 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -137,6 +137,20 @@
composer_callback_->SetVsyncService(nullptr);
}
+void HardwareComposer::UpdateEdidData(Hwc2::Composer* composer,
+ hwc2_display_t hw_id) {
+ const auto error = composer->getDisplayIdentificationData(
+ hw_id, &display_port_, &display_identification_data_);
+ if (error != android::hardware::graphics::composer::V2_1::Error::NONE) {
+ if (error !=
+ android::hardware::graphics::composer::V2_1::Error::UNSUPPORTED) {
+ ALOGI("hardware_composer: identification data error\n");
+ } else {
+ ALOGI("hardware_composer: identification data unsupported\n");
+ }
+ }
+}
+
bool HardwareComposer::Initialize(
Hwc2::Composer* composer, hwc2_display_t primary_display_id,
RequestDisplayCallback request_display_callback) {
@@ -164,6 +178,8 @@
"HardwareComposer: Failed to create interrupt event fd : %s",
strerror(errno));
+ UpdateEdidData(composer, primary_display_id);
+
post_thread_ = std::thread(&HardwareComposer::PostThread, this);
initialized_ = true;
@@ -988,6 +1004,9 @@
EnableDisplay(*external_display_, false);
}
+ // Update the cached edid data for the current display.
+ UpdateEdidData(composer_.get(), target_display_->id);
+
// Turn the new target display on.
EnableDisplay(*target_display_, true);
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index db0d6a7..989ce35 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -25,6 +25,7 @@
#include <private/dvr/shared_buffer_helpers.h>
#include <private/dvr/vsync_service.h>
+#include "DisplayHardware/DisplayIdentification.h"
#include "acquired_buffer.h"
#include "display_surface.h"
@@ -334,6 +335,14 @@
int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer);
void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
+ // Gets the edid data for the current active display (internal or external)
+ DisplayIdentificationData GetCurrentDisplayIdentificationData() {
+ return display_identification_data_;
+ }
+
+ // Gets the edid port for the current active display (internal or external)
+ uint8_t GetCurrentDisplayPort() { return display_port_; }
+
private:
DisplayParams GetDisplayParams(Hwc2::Composer* composer,
hwc2_display_t display, bool is_primary);
@@ -544,6 +553,11 @@
bool vsync_trace_parity_ = false;
sp<VsyncService> vsync_service_;
+ // Edid section.
+ void UpdateEdidData(Hwc2::Composer* composer, hwc2_display_t hw_id);
+ DisplayIdentificationData display_identification_data_;
+ uint8_t display_port_;
+
static constexpr int kPostThreadInterrupted = 1;
HardwareComposer(const HardwareComposer&) = delete;