diff options
author | 2024-12-10 15:11:28 -0500 | |
---|---|---|
committer | 2025-01-28 10:53:09 -0500 | |
commit | 0bf26cdb198b2b13b492a27de1701599f3b24458 (patch) | |
tree | 3673ebb7c2385eed2241de32a6b7e27cb55ad847 | |
parent | 04a3b4f2f512fdcba44a5f0434847659328f1a5c (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.cpp | 24 | ||||
-rw-r--r-- | libs/ui/include/ui/DisplayId.h | 9 | ||||
-rw-r--r-- | libs/ui/include/ui/DisplayIdentification.h | 5 | ||||
-rw-r--r-- | libs/ui/tests/DisplayIdentification_test.cpp | 16 |
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; |