1 /**
2 * Copyright (c) 2025, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <aidl/Gtest.h>
18 #include <aidl/Vintf.h>
19 #include <aidl/android/hardware/graphics/common/BlendMode.h>
20 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
21 #include <aidl/android/hardware/graphics/common/FRect.h>
22 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
23 #include <aidl/android/hardware/graphics/common/Rect.h>
24 #include <aidl/android/hardware/graphics/composer3/Composition.h>
25 #include <aidl/android/hardware/graphics/composer3/IComposer.h>
26 #include <android-base/properties.h>
27 #include <android/binder_process.h>
28 #include <android/hardware/graphics/composer3/ComposerClientReader.h>
29 #include <android/hardware/graphics/composer3/ComposerClientWriter.h>
30 #include <binder/ProcessState.h>
31 #include <gtest/gtest.h>
32 #include <ui/Fence.h>
33 #include <ui/GraphicBuffer.h>
34 #include <ui/PixelFormat.h>
35 #include <string>
36 #include <unordered_map>
37 #include "ComposerClientWrapper.h"
38
39 #undef LOG_TAG
40 #define LOG_TAG "VtsHalGraphicsComposer3_ConnectedDisplays"
41
42 namespace aidl::android::hardware::graphics::composer3::vts {
43
44 using namespace std::chrono_literals;
45 using namespace aidl::android::hardware::graphics::composer3::libhwc_aidl_test;
46
47 /**
48 * @class ConnectedDisplaysTest
49 * @brief A test suite for validating the HWC (Hardware Composer) API when multiple displays are
50 * present.
51 *
52 * This test suite is part of the VTS (Vendor Test Suite) and is designed to test the interactions
53 * between multiple displays using the HWC API. It ensures that the API behaves correctly when more
54 * than one display are present.
55 *
56 * @note The test requires at least two displays to be found. If only one display is found, the test
57 * will be skipped.
58 */
59 class ConnectedDisplaysTest : public ::testing::TestWithParam<std::string> {
60 protected:
SetUp()61 void SetUp() override {
62 mComposerClient = std::make_unique<ComposerClientWrapper>(GetParam());
63 ASSERT_TRUE(mComposerClient->createClient().isOk());
64
65 const auto& [status, displays] = mComposerClient->getDisplays();
66 ASSERT_TRUE(status.isOk());
67 mDisplays = displays;
68
69 // Skip test if there's only one display
70 if (mDisplays.size() <= 1) {
71 GTEST_SKIP() << "Test requires at least 2 displays, found " << mDisplays.size();
72 }
73
74 // explicitly disable vsync for all displays
75 for (const auto& display : mDisplays) {
76 EXPECT_TRUE(mComposerClient->setVsync(display.getDisplayId(), false).isOk());
77 }
78 mComposerClient->setVsyncAllowed(false);
79 }
80
TearDown()81 void TearDown() override {
82 ASSERT_TRUE(
83 mComposerClient->tearDown(std::unordered_map<int64_t, ComposerClientWriter*>{}));
84 mComposerClient.reset();
85 }
86
87 std::unique_ptr<ComposerClientWrapper> mComposerClient;
88 std::vector<DisplayWrapper> mDisplays;
89 static constexpr uint32_t kBufferSlotCount = 64;
90 };
91
92 /**
93 * Test that verifies display configurations can be changed independently without affecting other
94 * displays.
95 */
TEST_P(ConnectedDisplaysTest,IndependentConfigChange)96 TEST_P(ConnectedDisplaysTest, IndependentConfigChange) {
97 // Store initial configs for all displays
98 std::unordered_map<int64_t, int32_t> initialConfigs;
99 for (const auto& display : mDisplays) {
100 const auto& [activeStatus, activeConfig] =
101 mComposerClient->getActiveConfig(display.getDisplayId());
102 ASSERT_TRUE(activeStatus.isOk());
103 initialConfigs[display.getDisplayId()] = activeConfig;
104 }
105
106 for (auto& display : mDisplays) {
107 const auto& [status, configs] = mComposerClient->getDisplayConfigs(display.getDisplayId());
108 ASSERT_TRUE(status.isOk());
109 ASSERT_FALSE(configs.empty());
110
111 // Try to set each config
112 for (const auto& config : configs) {
113 if (config == initialConfigs[display.getDisplayId()]) continue;
114
115 EXPECT_TRUE(mComposerClient->setActiveConfig(&display, config).isOk());
116
117 // Verify other displays' configs remain unchanged
118 for (const auto& otherDisplay : mDisplays) {
119 if (otherDisplay.getDisplayId() != display.getDisplayId()) {
120 const auto& [otherStatus, otherConfig] =
121 mComposerClient->getActiveConfig(otherDisplay.getDisplayId());
122 EXPECT_TRUE(otherStatus.isOk());
123 EXPECT_EQ(otherConfig, initialConfigs[otherDisplay.getDisplayId()]);
124 }
125 }
126 }
127 // Restore original config
128 EXPECT_TRUE(
129 mComposerClient->setActiveConfig(&display, initialConfigs[display.getDisplayId()])
130 .isOk());
131 }
132 }
133
134 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConnectedDisplaysTest);
135 INSTANTIATE_TEST_SUITE_P(
136 PerInstance, ConnectedDisplaysTest,
137 testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
138 ::android::PrintInstanceNameToString);
139
140 } // namespace aidl::android::hardware::graphics::composer3::vts
141