Skip to content

Commit 0bf26cd

Browse files
committed
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
1 parent 04a3b4f commit 0bf26cd

4 files changed

Lines changed: 53 additions & 1 deletion

File tree

libs/ui/DisplayIdentification.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <string>
2727
#include <string_view>
2828

29+
#include <ftl/concat.h>
2930
#include <ftl/hash.h>
3031
#include <log/log.h>
3132
#include <ui/DisplayIdentification.h>
@@ -423,4 +424,27 @@ PhysicalDisplayId getVirtualDisplayId(uint32_t id) {
423424
return PhysicalDisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
424425
}
425426

427+
PhysicalDisplayId generateEdidDisplayId(const Edid& edid) {
428+
const ftl::Concat displayDetailsString{edid.manufacturerId,
429+
edid.productId,
430+
ftl::truncated<13>(edid.displayName),
431+
edid.manufactureWeek,
432+
edid.manufactureOrModelYear,
433+
edid.physicalSizeInCm.getWidth(),
434+
edid.physicalSizeInCm.getHeight()};
435+
436+
// String has to be cropped to 64 characters (at most) for ftl::stable_hash.
437+
// This is fine as the accuracy or completeness of the above fields is not
438+
// critical for a ID fabrication.
439+
const std::optional<uint64_t> hashedDisplayDetailsOpt =
440+
ftl::stable_hash(std::string_view(displayDetailsString.c_str(), 64));
441+
442+
// Combine the hashes via bit-shifted XORs.
443+
const uint64_t id = (hashedDisplayDetailsOpt.value_or(0) << 17) ^
444+
(edid.hashedBlockZeroSerialNumberOpt.value_or(0) >> 11) ^
445+
(edid.hashedDescriptorBlockSerialNumberOpt.value_or(0) << 23);
446+
447+
return PhysicalDisplayId::fromEdidHash(id);
448+
}
449+
426450
} // namespace android

libs/ui/include/ui/DisplayId.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,17 @@ struct PhysicalDisplayId : DisplayId {
8181
return PhysicalDisplayId(id);
8282
}
8383

84-
// Returns a stable ID based on EDID information.
84+
// Returns a stable ID based on EDID and port information.
8585
static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId,
8686
uint32_t modelHash) {
8787
return PhysicalDisplayId(FLAG_STABLE, port, manufacturerId, modelHash);
8888
}
8989

90+
// Returns a stable and consistent ID based exclusively on EDID information.
91+
static constexpr PhysicalDisplayId fromEdidHash(uint64_t hashedEdid) {
92+
return PhysicalDisplayId(hashedEdid);
93+
}
94+
9095
// Returns an unstable ID. If EDID is available using "fromEdid" is preferred.
9196
static constexpr PhysicalDisplayId fromPort(uint8_t port) {
9297
constexpr uint16_t kManufacturerId = 0;
@@ -103,6 +108,8 @@ struct PhysicalDisplayId : DisplayId {
103108
// Flag indicating that the ID is stable across reboots.
104109
static constexpr uint64_t FLAG_STABLE = 1ULL << 62;
105110

111+
using DisplayId::DisplayId;
112+
106113
constexpr PhysicalDisplayId(uint64_t flags, uint8_t port, uint16_t manufacturerId,
107114
uint32_t modelHash)
108115
: DisplayId(flags | (static_cast<uint64_t>(manufacturerId) << 40) |

libs/ui/include/ui/DisplayIdentification.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct Edid {
7474
std::optional<uint64_t> hashedDescriptorBlockSerialNumberOpt;
7575
PnpId pnpId;
7676
uint32_t modelHash;
77+
// Up to 13 characters of ASCII text terminated by LF and padded with SP.
7778
std::string_view displayName;
7879
uint8_t manufactureOrModelYear;
7980
uint8_t manufactureWeek;
@@ -91,4 +92,8 @@ std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
9192

9293
PhysicalDisplayId getVirtualDisplayId(uint32_t id);
9394

95+
// Generates a consistent, stable, and hashed display ID that is based on the
96+
// display's parsed EDID fields.
97+
PhysicalDisplayId generateEdidDisplayId(const Edid& edid);
98+
9499
} // namespace android

libs/ui/tests/DisplayIdentification_test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,22 @@ TEST(DisplayIdentificationTest, parseDisplayIdentificationData) {
376376
EXPECT_EQ(4633127902230889474, tertiaryInfo->id.value);
377377
}
378378

379+
TEST(DisplayIdentificationTest, generateEdidDisplayId) {
380+
const auto firstExternalDisplayEdidOpt = parseEdid(getExternalEdid());
381+
ASSERT_TRUE(firstExternalDisplayEdidOpt);
382+
const PhysicalDisplayId firstExternalDisplayId =
383+
generateEdidDisplayId(firstExternalDisplayEdidOpt.value());
384+
385+
const auto secondExternalDisplayEdidOpt = parseEdid(getExternalEedid());
386+
ASSERT_TRUE(secondExternalDisplayEdidOpt);
387+
const PhysicalDisplayId secondExternalDisplayId =
388+
generateEdidDisplayId(secondExternalDisplayEdidOpt.value());
389+
390+
// Display IDs should be unique.
391+
EXPECT_EQ(4067182673952280501u, firstExternalDisplayId.value);
392+
EXPECT_EQ(14712168404707886855u, secondExternalDisplayId.value);
393+
}
394+
379395
TEST(DisplayIdentificationTest, deviceProductInfo) {
380396
using ManufactureYear = DeviceProductInfo::ManufactureYear;
381397
using ManufactureWeekAndYear = DeviceProductInfo::ManufactureWeekAndYear;

0 commit comments

Comments
 (0)