Support per-port display configs in VTS

Bug: 277855934
Change-Id: I92e1615d8eb9466b40e02f8e2df8b3432e927af6
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index b047220..269abd1 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -129,33 +129,20 @@
         return {false, graphicBuffer};
     }
 
-    uint64_t getStableDisplayId(int64_t display) {
-        const auto& [status, identification] =
-                mComposerClient->getDisplayIdentificationData(display);
-        EXPECT_TRUE(status.isOk());
-
-        if (const auto info = ::android::parseDisplayIdentificationData(
-                    static_cast<uint8_t>(identification.port), identification.data)) {
-            return info->id.value;
-        }
-
-        return ::android::PhysicalDisplayId::fromPort(static_cast<uint8_t>(identification.port))
-                .value;
-    }
-
     // Gets the per-display XML config
     std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXml(int64_t display) {
-        std::stringstream pathBuilder;
-        pathBuilder << "/vendor/etc/displayconfig/display_id_" << getStableDisplayId(display)
-                    << ".xml";
-        const std::string path = pathBuilder.str();
-        auto document = std::make_unique<tinyxml2::XMLDocument>();
-        const tinyxml2::XMLError error = document->LoadFile(path.c_str());
-        if (error == tinyxml2::XML_SUCCESS) {
+
+        if (auto document = getDisplayConfigXmlByStableId(getStableDisplayId(display));
+                document != nullptr) {
             return document;
-        } else {
-            return nullptr;
         }
+
+        // Fallback to looking up a per-port config if no config exists for the full ID
+        if (auto document = getDisplayConfigXmlByPort(getPort(display)); document != nullptr) {
+            return document;
+        }
+
+        return nullptr;
     }
 
     // Gets the max display brightness for this display.
@@ -256,6 +243,53 @@
             }
         }
     }
+
+    uint8_t getPort(int64_t display) {
+        const auto& [status, identification] =
+                mComposerClient->getDisplayIdentificationData(display);
+        EXPECT_TRUE(status.isOk());
+        return static_cast<uint8_t>(identification.port);
+    }
+
+    uint64_t getStableDisplayId(int64_t display) {
+        const auto& [status, identification] =
+                mComposerClient->getDisplayIdentificationData(display);
+        EXPECT_TRUE(status.isOk());
+
+        if (const auto info = ::android::parseDisplayIdentificationData(
+                    static_cast<uint8_t>(identification.port), identification.data)) {
+            return info->id.value;
+        }
+
+        return ::android::PhysicalDisplayId::fromPort(static_cast<uint8_t>(identification.port))
+                .value;
+    }
+
+    std::unique_ptr<tinyxml2::XMLDocument> loadXml(const std::string& path) {
+        auto document = std::make_unique<tinyxml2::XMLDocument>();
+        const tinyxml2::XMLError error = document->LoadFile(path.c_str());
+        if (error != tinyxml2::XML_SUCCESS) {
+            ALOGD("%s: Failed to load config file: %s", __func__, path.c_str());
+            return nullptr;
+        }
+
+        ALOGD("%s: Successfully loaded config file: %s", __func__, path.c_str());
+        return document;
+    }
+
+    std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXmlByPort(uint8_t port) {
+        std::stringstream pathBuilder;
+        pathBuilder << "/vendor/etc/displayconfig/display_port_" << static_cast<uint32_t>(port)
+                    << ".xml";
+        return loadXml(pathBuilder.str());
+    }
+
+    std::unique_ptr<tinyxml2::XMLDocument> getDisplayConfigXmlByStableId(uint64_t stableId) {
+        std::stringstream pathBuilder;
+        pathBuilder << "/vendor/etc/displayconfig/display_id_" << stableId
+                    << ".xml";
+       return loadXml(pathBuilder.str());
+    }
 };
 
 class GraphicsCompositionTest : public GraphicsCompositionTestBase,