Skip to content

Commit c37c904

Browse files
committed
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
1 parent 3e96f94 commit c37c904

3 files changed

Lines changed: 34 additions & 3 deletions

File tree

libs/ui/DisplayIdentification.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919

2020
#include <algorithm>
2121
#include <cctype>
22+
#include <cstdint>
2223
#include <numeric>
2324
#include <optional>
2425
#include <span>
26+
#include <string>
27+
#include <string_view>
2528

2629
#include <ftl/hash.h>
2730
#include <log/log.h>
@@ -194,6 +197,21 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
194197
const uint16_t productId =
195198
static_cast<uint16_t>(edid[kProductIdOffset] | (edid[kProductIdOffset + 1] << 8));
196199

200+
// Bytes 12-15: display serial number, in little-endian (LSB). This field is
201+
// optional and its absence is marked by having all bytes set to 0x00.
202+
// Values do not represent ASCII characters.
203+
constexpr size_t kSerialNumberOffset = 12;
204+
if (edid.size() < kSerialNumberOffset + sizeof(uint32_t)) {
205+
ALOGE("Invalid EDID: block zero S/N is truncated.");
206+
return {};
207+
}
208+
const uint32_t blockZeroSerialNumber = edid[kSerialNumberOffset] +
209+
(edid[kSerialNumberOffset + 1] << 8) + (edid[kSerialNumberOffset + 2] << 16) +
210+
(edid[kSerialNumberOffset + 3] << 24);
211+
const auto hashedBlockZeroSNOpt = blockZeroSerialNumber == 0
212+
? std::nullopt
213+
: ftl::stable_hash(std::string_view(std::to_string(blockZeroSerialNumber)));
214+
197215
constexpr size_t kManufactureWeekOffset = 16;
198216
if (edid.size() < kManufactureWeekOffset + sizeof(uint8_t)) {
199217
ALOGE("Invalid EDID: manufacture week is truncated.");
@@ -350,6 +368,7 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
350368
return Edid{
351369
.manufacturerId = manufacturerId,
352370
.productId = productId,
371+
.hashedBlockZeroSerialNumberOpt = hashedBlockZeroSNOpt,
353372
.pnpId = *pnpId,
354373
.modelHash = modelHash,
355374
.displayName = displayName,

libs/ui/include/ui/DisplayIdentification.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct Cea861ExtensionBlock : ExtensionBlock {
6969
struct Edid {
7070
uint16_t manufacturerId;
7171
uint16_t productId;
72+
std::optional<uint64_t> hashedBlockZeroSerialNumberOpt;
7273
PnpId pnpId;
7374
uint32_t modelHash;
7475
std::string_view displayName;

libs/ui/tests/DisplayIdentification_test.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace android {
3333
namespace {
3434

3535
const unsigned char kInternalEdid[] =
36-
"\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
36+
"\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x4e\x61\xbc\x00"
3737
"\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
3838
"\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
3939
"\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
@@ -54,7 +54,7 @@ const unsigned char kExternalEdid[] =
5454

5555
// Extended EDID with timing extension.
5656
const unsigned char kExternalEedid[] =
57-
"\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00"
57+
"\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\xb1\x7f\x39\x05"
5858
"\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26"
5959
"\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00"
6060
"\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
@@ -112,7 +112,7 @@ const unsigned char kHisenseTvEdid[] =
112112
"\x07";
113113

114114
const unsigned char kCtlDisplayEdid[] =
115-
"\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x00\x00\x00\x00"
115+
"\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x30\x41\xab\x00"
116116
"\xff\x17\x01\x04\xa5\x34\x1d\x78\x3a\xa7\x25\xa4\x57\x51\xa0\x26"
117117
"\x10\x50\x54\xbf\xef\x80\xb3\x00\xa9\x40\x95\x00\x81\x40\x81\x80"
118118
"\x95\x0f\x71\x4f\x90\x40\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
@@ -191,6 +191,8 @@ TEST(DisplayIdentificationTest, parseEdid) {
191191
EXPECT_EQ(hash("121AT11-801"), 626564263);
192192
EXPECT_TRUE(edid->displayName.empty());
193193
EXPECT_EQ(12610, edid->productId);
194+
EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
195+
EXPECT_EQ(ftl::stable_hash("12345678"), edid->hashedBlockZeroSerialNumberOpt.value());
194196
EXPECT_EQ(21, edid->manufactureOrModelYear);
195197
EXPECT_EQ(0, edid->manufactureWeek);
196198
EXPECT_EQ(26, edid->physicalSizeInCm.width);
@@ -209,6 +211,8 @@ TEST(DisplayIdentificationTest, parseEdid) {
209211
EXPECT_EQ(hash("HP ZR30w"), 918492362);
210212
EXPECT_EQ("HP ZR30w", edid->displayName);
211213
EXPECT_EQ(10348, edid->productId);
214+
EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
215+
EXPECT_EQ(ftl::stable_hash("16843009"), edid->hashedBlockZeroSerialNumberOpt.value());
212216
EXPECT_EQ(22, edid->manufactureOrModelYear);
213217
EXPECT_EQ(2, edid->manufactureWeek);
214218
EXPECT_EQ(64, edid->physicalSizeInCm.width);
@@ -227,6 +231,8 @@ TEST(DisplayIdentificationTest, parseEdid) {
227231
EXPECT_EQ(hash("SAMSUNG"), 1201368132);
228232
EXPECT_EQ("SAMSUNG", edid->displayName);
229233
EXPECT_EQ(2302, edid->productId);
234+
EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
235+
EXPECT_EQ(ftl::stable_hash("87654321"), edid->hashedBlockZeroSerialNumberOpt.value());
230236
EXPECT_EQ(21, edid->manufactureOrModelYear);
231237
EXPECT_EQ(41, edid->manufactureWeek);
232238
EXPECT_EQ(16, edid->physicalSizeInCm.width);
@@ -251,6 +257,8 @@ TEST(DisplayIdentificationTest, parseEdid) {
251257
EXPECT_EQ(hash("Panasonic-TV"), 3876373262);
252258
EXPECT_EQ("Panasonic-TV", edid->displayName);
253259
EXPECT_EQ(41622, edid->productId);
260+
EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
261+
EXPECT_EQ(ftl::stable_hash("16843009"), edid->hashedBlockZeroSerialNumberOpt.value());
254262
EXPECT_EQ(29, edid->manufactureOrModelYear);
255263
EXPECT_EQ(0, edid->manufactureWeek);
256264
EXPECT_EQ(128, edid->physicalSizeInCm.width);
@@ -275,6 +283,7 @@ TEST(DisplayIdentificationTest, parseEdid) {
275283
EXPECT_EQ(hash("Hisense"), 2859844809);
276284
EXPECT_EQ("Hisense", edid->displayName);
277285
EXPECT_EQ(0, edid->productId);
286+
EXPECT_FALSE(edid->hashedBlockZeroSerialNumberOpt.has_value());
278287
EXPECT_EQ(29, edid->manufactureOrModelYear);
279288
EXPECT_EQ(18, edid->manufactureWeek);
280289
EXPECT_EQ(0, edid->physicalSizeInCm.width);
@@ -299,6 +308,8 @@ TEST(DisplayIdentificationTest, parseEdid) {
299308
EXPECT_EQ(hash("LP2361"), 1523181158);
300309
EXPECT_EQ("LP2361", edid->displayName);
301310
EXPECT_EQ(9373, edid->productId);
311+
EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
312+
EXPECT_EQ(ftl::stable_hash("11223344"), edid->hashedBlockZeroSerialNumberOpt.value());
302313
EXPECT_EQ(23, edid->manufactureOrModelYear);
303314
EXPECT_EQ(0xff, edid->manufactureWeek);
304315
EXPECT_EQ(52, edid->physicalSizeInCm.width);

0 commit comments

Comments
 (0)