summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Gil Dekel <gildekel@google.com> 2024-12-10 15:11:28 -0500
committer Gil Dekel <gildekel@google.com> 2025-01-28 10:53:09 -0500
commit0bf26cdb198b2b13b492a27de1701599f3b24458 (patch)
tree3673ebb7c2385eed2241de32a6b7e27cb55ad847
parent04a3b4f2f512fdcba44a5f0434847659328f1a5c (diff)
SF: Add EDID-ID Fabrication Logic
Adds logic to fabricate a display ID that is based solely on a given, pre-parsed EDID data. It does so by concatenating the EDID's generic fields, such as manufacturer ID, product ID, etc. as a string, and hash-combine them with the hashed values of the display serial numbers. All hash functions are stable in order to consistently reproduce display IDs when the same information is fed via the EDID blob. Flag: com.android.graphics.surfaceflinger.flags.stable_edid_ids Bug: 366042891 Test: N/A Change-Id: I7693d4b0ca9fee5ed190c3530a69300a8a530cd2
-rw-r--r--libs/ui/DisplayIdentification.cpp24
-rw-r--r--libs/ui/include/ui/DisplayId.h9
-rw-r--r--libs/ui/include/ui/DisplayIdentification.h5
-rw-r--r--libs/ui/tests/DisplayIdentification_test.cpp16
4 files changed, 53 insertions, 1 deletions
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index ee38f5044c..b7ef9b3738 100644
--- a/libs/ui/DisplayIdentification.cpp
+++ b/libs/ui/DisplayIdentification.cpp
@@ -26,6 +26,7 @@
#include <string>
#include <string_view>
+#include <ftl/concat.h>
#include <ftl/hash.h>
#include <log/log.h>
#include <ui/DisplayIdentification.h>
@@ -423,4 +424,27 @@ PhysicalDisplayId getVirtualDisplayId(uint32_t id) {
return PhysicalDisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
}
+PhysicalDisplayId generateEdidDisplayId(const Edid& edid) {
+ const ftl::Concat displayDetailsString{edid.manufacturerId,
+ edid.productId,
+ ftl::truncated<13>(edid.displayName),
+ edid.manufactureWeek,
+ edid.manufactureOrModelYear,
+ edid.physicalSizeInCm.getWidth(),
+ edid.physicalSizeInCm.getHeight()};
+
+ // String has to be cropped to 64 characters (at most) for ftl::stable_hash.
+ // This is fine as the accuracy or completeness of the above fields is not
+ // critical for a ID fabrication.
+ const std::optional<uint64_t> hashedDisplayDetailsOpt =
+ ftl::stable_hash(std::string_view(displayDetailsString.c_str(), 64));
+
+ // Combine the hashes via bit-shifted XORs.
+ const uint64_t id = (hashedDisplayDetailsOpt.value_or(0) << 17) ^
+ (edid.hashedBlockZeroSerialNumberOpt.value_or(0) >> 11) ^
+ (edid.hashedDescriptorBlockSerialNumberOpt.value_or(0) << 23);
+
+ return PhysicalDisplayId::fromEdidHash(id);
+}
+
} // namespace android
diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h
index 9ea6ceccdb..13ed754534 100644
--- a/libs/ui/include/ui/DisplayId.h
+++ b/libs/ui/include/ui/DisplayId.h
@@ -81,12 +81,17 @@ struct PhysicalDisplayId : DisplayId {
return PhysicalDisplayId(id);
}
- // Returns a stable ID based on EDID information.
+ // Returns a stable ID based on EDID and port information.
static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId,
uint32_t modelHash) {
return PhysicalDisplayId(FLAG_STABLE, port, manufacturerId, modelHash);
}
+ // Returns a stable and consistent ID based exclusively on EDID information.
+ static constexpr PhysicalDisplayId fromEdidHash(uint64_t hashedEdid) {
+ return PhysicalDisplayId(hashedEdid);
+ }
+
// Returns an unstable ID. If EDID is available using "fromEdid" is preferred.
static constexpr PhysicalDisplayId fromPort(uint8_t port) {
constexpr uint16_t kManufacturerId = 0;
@@ -103,6 +108,8 @@ private:
// Flag indicating that the ID is stable across reboots.
static constexpr uint64_t FLAG_STABLE = 1ULL << 62;
+ using DisplayId::DisplayId;
+
constexpr PhysicalDisplayId(uint64_t flags, uint8_t port, uint16_t manufacturerId,
uint32_t modelHash)
: DisplayId(flags | (static_cast<uint64_t>(manufacturerId) << 40) |
diff --git a/libs/ui/include/ui/DisplayIdentification.h b/libs/ui/include/ui/DisplayIdentification.h
index 5883dba05e..1e3449c004 100644
--- a/libs/ui/include/ui/DisplayIdentification.h
+++ b/libs/ui/include/ui/DisplayIdentification.h
@@ -74,6 +74,7 @@ struct Edid {
std::optional<uint64_t> hashedDescriptorBlockSerialNumberOpt;
PnpId pnpId;
uint32_t modelHash;
+ // Up to 13 characters of ASCII text terminated by LF and padded with SP.
std::string_view displayName;
uint8_t manufactureOrModelYear;
uint8_t manufactureWeek;
@@ -91,4 +92,8 @@ std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
PhysicalDisplayId getVirtualDisplayId(uint32_t id);
+// Generates a consistent, stable, and hashed display ID that is based on the
+// display's parsed EDID fields.
+PhysicalDisplayId generateEdidDisplayId(const Edid& edid);
+
} // namespace android
diff --git a/libs/ui/tests/DisplayIdentification_test.cpp b/libs/ui/tests/DisplayIdentification_test.cpp
index fdcf1126bd..75c71a598e 100644
--- a/libs/ui/tests/DisplayIdentification_test.cpp
+++ b/libs/ui/tests/DisplayIdentification_test.cpp
@@ -376,6 +376,22 @@ TEST(DisplayIdentificationTest, parseDisplayIdentificationData) {
EXPECT_EQ(4633127902230889474, tertiaryInfo->id.value);
}
+TEST(DisplayIdentificationTest, generateEdidDisplayId) {
+ const auto firstExternalDisplayEdidOpt = parseEdid(getExternalEdid());
+ ASSERT_TRUE(firstExternalDisplayEdidOpt);
+ const PhysicalDisplayId firstExternalDisplayId =
+ generateEdidDisplayId(firstExternalDisplayEdidOpt.value());
+
+ const auto secondExternalDisplayEdidOpt = parseEdid(getExternalEedid());
+ ASSERT_TRUE(secondExternalDisplayEdidOpt);
+ const PhysicalDisplayId secondExternalDisplayId =
+ generateEdidDisplayId(secondExternalDisplayEdidOpt.value());
+
+ // Display IDs should be unique.
+ EXPECT_EQ(4067182673952280501u, firstExternalDisplayId.value);
+ EXPECT_EQ(14712168404707886855u, secondExternalDisplayId.value);
+}
+
TEST(DisplayIdentificationTest, deviceProductInfo) {
using ManufactureYear = DeviceProductInfo::ManufactureYear;
using ManufactureWeekAndYear = DeviceProductInfo::ManufactureWeekAndYear;