diff options
author | 2024-11-13 16:53:33 -0500 | |
---|---|---|
committer | 2024-11-16 01:30:59 -0500 | |
commit | c37c90444774da117f8a4eef14b091f0a54086f2 (patch) | |
tree | 9d4bea5da983aef37450e238b2f44add9c79db5b | |
parent | 3e96f94d2cda8e5c9180e116aac6c57537fb970c (diff) |
SF: Parse, hash, and cache block 0 serial number
More EDID fields are required as a part of migrating to EDID-based
display IDs. This CL parses the device's serial number from bytes 12-15
of block 0 in the EDID blob, hashes it using a stable hash, and serves
it as a part of the Edid struct.
Later, amongst others, this value will be used to fabricate a unique
display ID that is based on the display's EDID.
See:
1. EDID spec: https://glenwing.github.io/docs/VESA-EEDID-A2.pdf
2. https://en.wikipedia.org/wiki/Extended_Display_Identification_Data#Structure,_version_1.4
Flag: com.android.graphics.surfaceflinger.flags.stable_edid_ids
Bug: 378923334
Test: DisplayIdentification_test
Change-Id: I8e5c79f2f51c2fd2085dfaba7f5c45fbc698cbcb
-rw-r--r-- | libs/ui/DisplayIdentification.cpp | 19 | ||||
-rw-r--r-- | libs/ui/include/ui/DisplayIdentification.h | 1 | ||||
-rw-r--r-- | libs/ui/tests/DisplayIdentification_test.cpp | 17 |
3 files changed, 34 insertions, 3 deletions
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp index 503f92ff32..5cdaa71627 100644 --- a/libs/ui/DisplayIdentification.cpp +++ b/libs/ui/DisplayIdentification.cpp @@ -19,9 +19,12 @@ #include <algorithm> #include <cctype> +#include <cstdint> #include <numeric> #include <optional> #include <span> +#include <string> +#include <string_view> #include <ftl/hash.h> #include <log/log.h> @@ -194,6 +197,21 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { const uint16_t productId = static_cast<uint16_t>(edid[kProductIdOffset] | (edid[kProductIdOffset + 1] << 8)); + // Bytes 12-15: display serial number, in little-endian (LSB). This field is + // optional and its absence is marked by having all bytes set to 0x00. + // Values do not represent ASCII characters. + constexpr size_t kSerialNumberOffset = 12; + if (edid.size() < kSerialNumberOffset + sizeof(uint32_t)) { + ALOGE("Invalid EDID: block zero S/N is truncated."); + return {}; + } + const uint32_t blockZeroSerialNumber = edid[kSerialNumberOffset] + + (edid[kSerialNumberOffset + 1] << 8) + (edid[kSerialNumberOffset + 2] << 16) + + (edid[kSerialNumberOffset + 3] << 24); + const auto hashedBlockZeroSNOpt = blockZeroSerialNumber == 0 + ? std::nullopt + : ftl::stable_hash(std::string_view(std::to_string(blockZeroSerialNumber))); + constexpr size_t kManufactureWeekOffset = 16; if (edid.size() < kManufactureWeekOffset + sizeof(uint8_t)) { ALOGE("Invalid EDID: manufacture week is truncated."); @@ -350,6 +368,7 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { return Edid{ .manufacturerId = manufacturerId, .productId = productId, + .hashedBlockZeroSerialNumberOpt = hashedBlockZeroSNOpt, .pnpId = *pnpId, .modelHash = modelHash, .displayName = displayName, diff --git a/libs/ui/include/ui/DisplayIdentification.h b/libs/ui/include/ui/DisplayIdentification.h index 3f938d6c96..85e5cee490 100644 --- a/libs/ui/include/ui/DisplayIdentification.h +++ b/libs/ui/include/ui/DisplayIdentification.h @@ -69,6 +69,7 @@ struct Cea861ExtensionBlock : ExtensionBlock { struct Edid { uint16_t manufacturerId; uint16_t productId; + std::optional<uint64_t> hashedBlockZeroSerialNumberOpt; PnpId pnpId; uint32_t modelHash; std::string_view displayName; diff --git a/libs/ui/tests/DisplayIdentification_test.cpp b/libs/ui/tests/DisplayIdentification_test.cpp index cf0e98b0c6..fbbe719be8 100644 --- a/libs/ui/tests/DisplayIdentification_test.cpp +++ b/libs/ui/tests/DisplayIdentification_test.cpp @@ -33,7 +33,7 @@ namespace android { namespace { const unsigned char kInternalEdid[] = - "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00" + "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x4e\x61\xbc\x00" "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27" "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30" @@ -54,7 +54,7 @@ const unsigned char kExternalEdid[] = // Extended EDID with timing extension. const unsigned char kExternalEedid[] = - "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00" + "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\xb1\x7f\x39\x05" "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26" "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00" "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c" @@ -112,7 +112,7 @@ const unsigned char kHisenseTvEdid[] = "\x07"; const unsigned char kCtlDisplayEdid[] = - "\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x00\x00\x00\x00" + "\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x30\x41\xab\x00" "\xff\x17\x01\x04\xa5\x34\x1d\x78\x3a\xa7\x25\xa4\x57\x51\xa0\x26" "\x10\x50\x54\xbf\xef\x80\xb3\x00\xa9\x40\x95\x00\x81\x40\x81\x80" "\x95\x0f\x71\x4f\x90\x40\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c" @@ -191,6 +191,8 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(hash("121AT11-801"), 626564263); EXPECT_TRUE(edid->displayName.empty()); EXPECT_EQ(12610, edid->productId); + EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value()); + EXPECT_EQ(ftl::stable_hash("12345678"), edid->hashedBlockZeroSerialNumberOpt.value()); EXPECT_EQ(21, edid->manufactureOrModelYear); EXPECT_EQ(0, edid->manufactureWeek); EXPECT_EQ(26, edid->physicalSizeInCm.width); @@ -209,6 +211,8 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(hash("HP ZR30w"), 918492362); EXPECT_EQ("HP ZR30w", edid->displayName); EXPECT_EQ(10348, edid->productId); + EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value()); + EXPECT_EQ(ftl::stable_hash("16843009"), edid->hashedBlockZeroSerialNumberOpt.value()); EXPECT_EQ(22, edid->manufactureOrModelYear); EXPECT_EQ(2, edid->manufactureWeek); EXPECT_EQ(64, edid->physicalSizeInCm.width); @@ -227,6 +231,8 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(hash("SAMSUNG"), 1201368132); EXPECT_EQ("SAMSUNG", edid->displayName); EXPECT_EQ(2302, edid->productId); + EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value()); + EXPECT_EQ(ftl::stable_hash("87654321"), edid->hashedBlockZeroSerialNumberOpt.value()); EXPECT_EQ(21, edid->manufactureOrModelYear); EXPECT_EQ(41, edid->manufactureWeek); EXPECT_EQ(16, edid->physicalSizeInCm.width); @@ -251,6 +257,8 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(hash("Panasonic-TV"), 3876373262); EXPECT_EQ("Panasonic-TV", edid->displayName); EXPECT_EQ(41622, edid->productId); + EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value()); + EXPECT_EQ(ftl::stable_hash("16843009"), edid->hashedBlockZeroSerialNumberOpt.value()); EXPECT_EQ(29, edid->manufactureOrModelYear); EXPECT_EQ(0, edid->manufactureWeek); EXPECT_EQ(128, edid->physicalSizeInCm.width); @@ -275,6 +283,7 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(hash("Hisense"), 2859844809); EXPECT_EQ("Hisense", edid->displayName); EXPECT_EQ(0, edid->productId); + EXPECT_FALSE(edid->hashedBlockZeroSerialNumberOpt.has_value()); EXPECT_EQ(29, edid->manufactureOrModelYear); EXPECT_EQ(18, edid->manufactureWeek); EXPECT_EQ(0, edid->physicalSizeInCm.width); @@ -299,6 +308,8 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(hash("LP2361"), 1523181158); EXPECT_EQ("LP2361", edid->displayName); EXPECT_EQ(9373, edid->productId); + EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value()); + EXPECT_EQ(ftl::stable_hash("11223344"), edid->hashedBlockZeroSerialNumberOpt.value()); EXPECT_EQ(23, edid->manufactureOrModelYear); EXPECT_EQ(0xff, edid->manufactureWeek); EXPECT_EQ(52, edid->physicalSizeInCm.width); |