Loading libs/ui/DisplayIdentification.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 libs/ui/include/ui/DisplayId.h +8 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) | Loading libs/ui/include/ui/DisplayIdentification.h +5 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 libs/ui/tests/DisplayIdentification_test.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
libs/ui/DisplayIdentification.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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
libs/ui/include/ui/DisplayId.h +8 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) | Loading
libs/ui/include/ui/DisplayIdentification.h +5 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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
libs/ui/tests/DisplayIdentification_test.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -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; Loading