VTS: Test that configs in a group differ only by vsync period

All display configs in a config group must have the same resolution
and DPI (if DPI attributes are supported by HWC).

Fixes: 172902326
Test: atest VtsHalGraphicsComposerV2_4TargetTest
Change-Id: Id86fe7983a12e33d2d9c3b88ee68d6e18485e87d
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 8077f08..50f282f 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -19,6 +19,8 @@
 #include <algorithm>
 #include <regex>
 #include <thread>
+#include <unordered_map>
+#include <utility>
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -285,6 +287,59 @@
     }
 }
 
+TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4_ConfigsInAGroupDifferOnlyByVsyncPeriod) {
+    struct Resolution {
+        int32_t width, height;
+    };
+    struct Dpi {
+        int32_t x, y;
+    };
+    for (const auto& display : mDisplays) {
+        std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
+        std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
+        std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
+        for (auto config : configs) {
+            const auto configGroup = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::CONFIG_GROUP);
+            const auto width = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::WIDTH);
+            const auto height = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::HEIGHT);
+            if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
+                configGroupToResolutionMap[configGroup] = {width, height};
+            }
+            EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
+            EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
+
+            int32_t dpiX = -1;
+            mComposerClient->getRaw()->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::DPI_X,
+                    [&](const auto& tmpError, const auto& value) {
+                        if (tmpError == Error::NONE) {
+                            dpiX = value;
+                        }
+                    });
+            int32_t dpiY = -1;
+            mComposerClient->getRaw()->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::DPI_Y,
+                    [&](const auto& tmpError, const auto& value) {
+                        if (tmpError == Error::NONE) {
+                            dpiY = value;
+                        }
+                    });
+            if (dpiX == -1 && dpiY == -1) {
+                continue;
+            }
+
+            if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
+                configGroupToDpiMap[configGroup] = {dpiX, dpiY};
+            }
+            EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
+            EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
+        }
+    }
+}
+
 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
     VsyncPeriodNanos vsyncPeriodNanos;
     EXPECT_EQ(Error::BAD_DISPLAY,