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
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index ee38f50..b7ef9b3 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 @@
     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