1 /*
2 * Copyright 2019 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 #define LOG_TAG "graphics_composer_hidl_hal_test@2.4"
18
19 #include <algorithm>
20 #include <regex>
21 #include <thread>
22
23 #include <android-base/logging.h>
24 #include <android-base/properties.h>
25 #include <composer-command-buffer/2.4/ComposerCommandBuffer.h>
26 #include <composer-vts/2.4/ComposerVts.h>
27 #include <composer-vts/2.4/GraphicsComposerCallback.h>
28 #include <composer-vts/2.4/TestCommandReader.h>
29 #include <gtest/gtest.h>
30 #include <hidl/GtestPrinter.h>
31 #include <hidl/ServiceManagement.h>
32 #include <ui/GraphicBuffer.h>
33 #include <utils/Timers.h>
34
35 namespace android {
36 namespace hardware {
37 namespace graphics {
38 namespace composer {
39 namespace V2_4 {
40 namespace vts {
41 namespace {
42
43 using namespace std::chrono_literals;
44
45 using common::V1_0::BufferUsage;
46 using common::V1_1::RenderIntent;
47 using common::V1_2::ColorMode;
48 using common::V1_2::Dataspace;
49 using common::V1_2::PixelFormat;
50 using V2_1::Layer;
51 using V2_2::Transform;
52
53 using ContentType = IComposerClient::ContentType;
54 using DisplayCapability = IComposerClient::DisplayCapability;
55
56 class VtsDisplay {
57 public:
VtsDisplay(Display display,int32_t displayWidth,int32_t displayHeight)58 VtsDisplay(Display display, int32_t displayWidth, int32_t displayHeight)
59 : mDisplay(display), mDisplayWidth(displayWidth), mDisplayHeight(displayHeight) {}
60
get() const61 Display get() const { return mDisplay; }
62
getCrop() const63 IComposerClient::FRect getCrop() const {
64 return {0, 0, static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)};
65 }
66
getFrameRect() const67 IComposerClient::Rect getFrameRect() const { return {0, 0, mDisplayWidth, mDisplayHeight}; }
68
setDimensions(int32_t displayWidth,int32_t displayHeight)69 void setDimensions(int32_t displayWidth, int32_t displayHeight) {
70 mDisplayWidth = displayWidth;
71 mDisplayHeight = displayHeight;
72 }
73
74 private:
75 const Display mDisplay;
76 int32_t mDisplayWidth;
77 int32_t mDisplayHeight;
78 };
79
80 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
81 protected:
SetUp()82 void SetUp() override {
83 ASSERT_NO_FATAL_FAILURE(
84 mComposer = std::make_unique<Composer>(IComposer::getService(GetParam())));
85 ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
86
87 mComposerCallback = new GraphicsComposerCallback;
88 mComposerClient->registerCallback_2_4(mComposerCallback);
89
90 // assume the first displays are built-in and are never removed
91 mDisplays = waitForDisplays();
92
93 mInvalidDisplayId = GetInvalidDisplayId();
94
95 // explicitly disable vsync
96 for (const auto& display : mDisplays) {
97 mComposerClient->setVsyncEnabled(display.get(), false);
98 }
99 mComposerCallback->setVsyncAllowed(false);
100
101 mWriter = std::make_unique<CommandWriterBase>(1024);
102 mReader = std::make_unique<TestCommandReader>();
103 }
104
TearDown()105 void TearDown() override {
106 ASSERT_EQ(0, mReader->mErrors.size());
107 ASSERT_EQ(0, mReader->mCompositionChanges.size());
108
109 if (mComposerCallback != nullptr) {
110 EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
111 EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
112 EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
113 EXPECT_EQ(0, mComposerCallback->getInvalidVsync_2_4Count());
114 EXPECT_EQ(0, mComposerCallback->getInvalidVsyncPeriodChangeCount());
115 EXPECT_EQ(0, mComposerCallback->getInvalidSeamlessPossibleCount());
116 }
117 }
118
119 // returns an invalid display id (one that has not been registered to a
120 // display. Currently assuming that a device will never have close to
121 // std::numeric_limit<uint64_t>::max() displays registered while running tests
GetInvalidDisplayId()122 Display GetInvalidDisplayId() {
123 uint64_t id = std::numeric_limits<uint64_t>::max();
124 while (id > 0) {
125 if (std::none_of(mDisplays.begin(), mDisplays.end(),
126 [&](const VtsDisplay& display) { return id == display.get(); })) {
127 return id;
128 }
129 id--;
130 }
131
132 return 0;
133 }
134
135 // returns an invalid config id (one that has not been registered to a
136 // display). Currently assuming that a device will never have close to
137 // std::numeric_limit<uint64_t>::max() configs registered while running tests
GetInvalidConfigId(Display display)138 Display GetInvalidConfigId(Display display) {
139 std::vector<Config> validConfigs = mComposerClient->getDisplayConfigs(display);
140 uint64_t id = std::numeric_limits<uint64_t>::max();
141 while (id > 0) {
142 if (std::find(validConfigs.begin(), validConfigs.end(), id) == validConfigs.end()) {
143 return id;
144 }
145 id--;
146 }
147
148 return 0;
149 }
150
execute()151 void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
152
allocate(int32_t width,int32_t height)153 sp<GraphicBuffer> allocate(int32_t width, int32_t height) {
154 auto result = sp<GraphicBuffer>::make(
155 width, height, static_cast<int32_t>(PixelFormat::RGBA_8888), /*layerCount*/ 1,
156 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
157 BufferUsage::COMPOSER_OVERLAY));
158 if (result->initCheck() != STATUS_OK) {
159 return nullptr;
160 }
161 return result;
162 }
163
164 struct TestParameters {
165 nsecs_t delayForChange;
166 bool refreshMiss;
167 };
168
169 void Test_setActiveConfigWithConstraints(const TestParameters& params);
170
171 void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline*);
172
173 void waitForVsyncPeriodChange(Display display, const VsyncPeriodChangeTimeline& timeline,
174 int64_t desiredTimeNanos, int64_t oldPeriodNanos,
175 int64_t newPeriodNanos);
176
177 std::unique_ptr<ComposerClient> mComposerClient;
178 std::vector<VtsDisplay> mDisplays;
179 Display mInvalidDisplayId;
180
forEachTwoConfigs(Display display,std::function<void (Config,Config)> func)181 void forEachTwoConfigs(Display display, std::function<void(Config, Config)> func) {
182 const auto displayConfigs = mComposerClient->getDisplayConfigs(display);
183 for (const Config config1 : displayConfigs) {
184 for (const Config config2 : displayConfigs) {
185 if (config1 != config2) {
186 func(config1, config2);
187 }
188 }
189 }
190 }
191
192 void Test_setContentType(const ContentType& contentType, const char* contentTypeStr);
193 void Test_setContentTypeForDisplay(const Display& display,
194 const std::vector<ContentType>& capabilities,
195 const ContentType& contentType, const char* contentTypeStr);
196
setActiveConfigWithConstraints(VtsDisplay & display,Config config,const IComposerClient::VsyncPeriodChangeConstraints & constraints,VsyncPeriodChangeTimeline * timeline)197 Error setActiveConfigWithConstraints(
198 VtsDisplay& display, Config config,
199 const IComposerClient::VsyncPeriodChangeConstraints& constraints,
200 VsyncPeriodChangeTimeline* timeline) {
201 const auto error = mComposerClient->setActiveConfigWithConstraints(display.get(), config,
202 constraints, timeline);
203 if (error == Error::NONE) {
204 const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
205 display.get(), config, IComposerClient::Attribute::WIDTH);
206 const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
207 display.get(), config, IComposerClient::Attribute::HEIGHT);
208 display.setDimensions(displayWidth, displayHeight);
209 }
210 return error;
211 }
212
setActiveConfig(VtsDisplay & display,Config config)213 void setActiveConfig(VtsDisplay& display, Config config) {
214 mComposerClient->setActiveConfig(display.get(), config);
215 const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
216 display.get(), config, IComposerClient::Attribute::WIDTH);
217 const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
218 display.get(), config, IComposerClient::Attribute::HEIGHT);
219 display.setDimensions(displayWidth, displayHeight);
220 }
221
222 private:
223 // use the slot count usually set by SF
224 static constexpr uint32_t kBufferSlotCount = 64;
225
waitForDisplays()226 std::vector<VtsDisplay> waitForDisplays() {
227 while (true) {
228 // Sleep for a small period of time to allow all built-in displays
229 // to post hotplug events
230 std::this_thread::sleep_for(5ms);
231 std::vector<Display> displays = mComposerCallback->getDisplays();
232 if (displays.empty()) {
233 continue;
234 }
235
236 std::vector<VtsDisplay> vtsDisplays;
237 vtsDisplays.reserve(displays.size());
238 for (Display display : displays) {
239 const Config activeConfig = mComposerClient->getActiveConfig(display);
240 const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
241 display, activeConfig, IComposerClient::Attribute::WIDTH);
242 const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
243 display, activeConfig, IComposerClient::Attribute::HEIGHT);
244 vtsDisplays.emplace_back(VtsDisplay{display, displayWidth, displayHeight});
245 }
246
247 return vtsDisplays;
248 }
249 }
250
251 std::unique_ptr<Composer> mComposer;
252 std::unique_ptr<CommandWriterBase> mWriter;
253 std::unique_ptr<TestCommandReader> mReader;
254 sp<GraphicsComposerCallback> mComposerCallback;
255 };
256
TEST_P(GraphicsComposerHidlTest,getDisplayCapabilitiesBadDisplay)257 TEST_P(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
258 std::vector<IComposerClient::DisplayCapability> capabilities;
259 const auto error = mComposerClient->getDisplayCapabilities(mInvalidDisplayId, &capabilities);
260 EXPECT_EQ(Error::BAD_DISPLAY, error);
261 }
262
TEST_P(GraphicsComposerHidlTest,getDisplayCapabilities)263 TEST_P(GraphicsComposerHidlTest, getDisplayCapabilities) {
264 for (const auto& display : mDisplays) {
265 std::vector<IComposerClient::DisplayCapability> capabilities;
266 EXPECT_EQ(Error::NONE,
267 mComposerClient->getDisplayCapabilities(display.get(), &capabilities));
268 }
269 }
270
TEST_P(GraphicsComposerHidlTest,getDisplayConnectionType)271 TEST_P(GraphicsComposerHidlTest, getDisplayConnectionType) {
272 IComposerClient::DisplayConnectionType type;
273 EXPECT_EQ(Error::BAD_DISPLAY,
274 mComposerClient->getDisplayConnectionType(mInvalidDisplayId, &type));
275
276 for (const auto& display : mDisplays) {
277 EXPECT_EQ(Error::NONE, mComposerClient->getDisplayConnectionType(display.get(), &type));
278 }
279 }
280
TEST_P(GraphicsComposerHidlTest,GetDisplayAttribute_2_4)281 TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4) {
282 for (const auto& display : mDisplays) {
283 std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
284 for (auto config : configs) {
285 const std::array<IComposerClient::Attribute, 4> requiredAttributes = {{
286 IComposerClient::Attribute::WIDTH,
287 IComposerClient::Attribute::HEIGHT,
288 IComposerClient::Attribute::VSYNC_PERIOD,
289 IComposerClient::Attribute::CONFIG_GROUP,
290 }};
291 for (auto attribute : requiredAttributes) {
292 mComposerClient->getRaw()->getDisplayAttribute_2_4(
293 display.get(), config, attribute,
294 [&](const auto& tmpError, const auto& value) {
295 EXPECT_EQ(Error::NONE, tmpError);
296 EXPECT_NE(-1, value);
297 });
298 }
299
300 const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
301 IComposerClient::Attribute::DPI_X,
302 IComposerClient::Attribute::DPI_Y,
303 }};
304 for (auto attribute : optionalAttributes) {
305 mComposerClient->getRaw()->getDisplayAttribute_2_4(
306 display.get(), config, attribute, [&](const auto& tmpError, const auto&) {
307 EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
308 });
309 }
310 }
311 }
312 }
313
TEST_P(GraphicsComposerHidlTest,getDisplayVsyncPeriod_BadDisplay)314 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
315 VsyncPeriodNanos vsyncPeriodNanos;
316 EXPECT_EQ(Error::BAD_DISPLAY,
317 mComposerClient->getDisplayVsyncPeriod(mInvalidDisplayId, &vsyncPeriodNanos));
318 }
319
TEST_P(GraphicsComposerHidlTest,getDisplayVsyncPeriod)320 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod) {
321 for (VtsDisplay& display : mDisplays) {
322 for (Config config : mComposerClient->getDisplayConfigs(display.get())) {
323 VsyncPeriodNanos expectedVsyncPeriodNanos = mComposerClient->getDisplayAttribute_2_4(
324 display.get(), config,
325 IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
326
327 VsyncPeriodChangeTimeline timeline;
328 IComposerClient::VsyncPeriodChangeConstraints constraints;
329
330 constraints.desiredTimeNanos = systemTime();
331 constraints.seamlessRequired = false;
332 EXPECT_EQ(Error::NONE,
333 setActiveConfigWithConstraints(display, config, constraints, &timeline));
334
335 if (timeline.refreshRequired) {
336 sendRefreshFrame(display, &timeline);
337 }
338 waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
339 expectedVsyncPeriodNanos);
340
341 VsyncPeriodNanos vsyncPeriodNanos;
342 int retryCount = 100;
343 do {
344 std::this_thread::sleep_for(10ms);
345 vsyncPeriodNanos = 0;
346 EXPECT_EQ(Error::NONE,
347 mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
348 --retryCount;
349 } while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
350
351 EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
352
353 // Make sure that the vsync period stays the same if the active config is not changed.
354 auto timeout = 1ms;
355 for (int i = 0; i < 10; i++) {
356 std::this_thread::sleep_for(timeout);
357 timeout *= 2;
358 vsyncPeriodNanos = 0;
359 EXPECT_EQ(Error::NONE,
360 mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
361 EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
362 }
363 }
364 }
365 }
366
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_BadDisplay)367 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_BadDisplay) {
368 VsyncPeriodChangeTimeline timeline;
369 IComposerClient::VsyncPeriodChangeConstraints constraints;
370
371 constraints.seamlessRequired = false;
372 constraints.desiredTimeNanos = systemTime();
373
374 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setActiveConfigWithConstraints(
375 mInvalidDisplayId, Config(0), constraints, &timeline));
376 }
377
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_BadConfig)378 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_BadConfig) {
379 VsyncPeriodChangeTimeline timeline;
380 IComposerClient::VsyncPeriodChangeConstraints constraints;
381
382 constraints.seamlessRequired = false;
383 constraints.desiredTimeNanos = systemTime();
384
385 for (VtsDisplay& display : mDisplays) {
386 Config invalidConfigId = GetInvalidConfigId(display.get());
387 EXPECT_EQ(Error::BAD_CONFIG,
388 setActiveConfigWithConstraints(display, invalidConfigId, constraints, &timeline));
389 }
390 }
391
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_SeamlessNotAllowed)392 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
393 VsyncPeriodChangeTimeline timeline;
394 IComposerClient::VsyncPeriodChangeConstraints constraints;
395
396 constraints.seamlessRequired = true;
397 constraints.desiredTimeNanos = systemTime();
398
399 for (VtsDisplay& display : mDisplays) {
400 forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
401 const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
402 display.get(), config1,
403 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
404 const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
405 display.get(), config2,
406 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
407 if (configGroup1 != configGroup2) {
408 setActiveConfig(display, config1);
409 sendRefreshFrame(display, nullptr);
410 EXPECT_EQ(Error::SEAMLESS_NOT_ALLOWED,
411 setActiveConfigWithConstraints(display, config2, constraints, &timeline));
412 }
413 });
414 }
415 }
416
toTimePoint(nsecs_t time)417 static inline auto toTimePoint(nsecs_t time) {
418 return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
419 }
420
sendRefreshFrame(const VtsDisplay & display,const VsyncPeriodChangeTimeline * timeline)421 void GraphicsComposerHidlTest::sendRefreshFrame(const VtsDisplay& display,
422 const VsyncPeriodChangeTimeline* timeline) {
423 if (timeline != nullptr) {
424 // Refresh time should be before newVsyncAppliedTimeNanos
425 EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
426
427 std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
428 }
429
430 mWriter->selectDisplay(display.get());
431 mComposerClient->setPowerMode(display.get(), V2_1::IComposerClient::PowerMode::ON);
432 mComposerClient->setColorMode_2_3(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
433
434 IComposerClient::FRect displayCrop = display.getCrop();
435 int32_t displayWidth = static_cast<int32_t>(std::ceilf(displayCrop.right - displayCrop.left));
436 int32_t displayHeight = static_cast<int32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
437 Layer layer;
438 ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(display.get(), kBufferSlotCount));
439
440 {
441 auto handle = allocate(displayWidth, displayHeight);
442 ASSERT_NE(nullptr, handle.get());
443
444 mWriter->selectLayer(layer);
445 mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
446 mWriter->setLayerDisplayFrame(display.getFrameRect());
447 mWriter->setLayerPlaneAlpha(1);
448 mWriter->setLayerSourceCrop(display.getCrop());
449 mWriter->setLayerTransform(static_cast<Transform>(0));
450 mWriter->setLayerVisibleRegion(
451 std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
452 mWriter->setLayerZOrder(10);
453 mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
454 mWriter->setLayerSurfaceDamage(
455 std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
456 mWriter->setLayerBuffer(0, handle->handle, -1);
457 mWriter->setLayerDataspace(Dataspace::UNKNOWN);
458
459 mWriter->validateDisplay();
460 execute();
461 ASSERT_EQ(0, mReader->mErrors.size());
462 mReader->mCompositionChanges.clear();
463
464 mWriter->presentDisplay();
465 execute();
466 ASSERT_EQ(0, mReader->mErrors.size());
467 }
468
469 {
470 auto handle = allocate(displayWidth, displayHeight);
471 ASSERT_NE(nullptr, handle.get());
472
473 mWriter->selectLayer(layer);
474 mWriter->setLayerBuffer(0, handle->handle, -1);
475 mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
476 mWriter->validateDisplay();
477 execute();
478 ASSERT_EQ(0, mReader->mErrors.size());
479 mReader->mCompositionChanges.clear();
480
481 mWriter->presentDisplay();
482 execute();
483 }
484
485 ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(display.get(), layer));
486 }
487
waitForVsyncPeriodChange(Display display,const VsyncPeriodChangeTimeline & timeline,int64_t desiredTimeNanos,int64_t oldPeriodNanos,int64_t newPeriodNanos)488 void GraphicsComposerHidlTest::waitForVsyncPeriodChange(Display display,
489 const VsyncPeriodChangeTimeline& timeline,
490 int64_t desiredTimeNanos,
491 int64_t oldPeriodNanos,
492 int64_t newPeriodNanos) {
493 const auto CHANGE_DEADLINE = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
494 while (std::chrono::steady_clock::now() <= CHANGE_DEADLINE) {
495 VsyncPeriodNanos vsyncPeriodNanos;
496 EXPECT_EQ(Error::NONE, mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
497 if (systemTime() <= desiredTimeNanos) {
498 EXPECT_EQ(vsyncPeriodNanos, oldPeriodNanos);
499 } else if (vsyncPeriodNanos == newPeriodNanos) {
500 break;
501 }
502 std::this_thread::sleep_for(std::chrono::nanoseconds(oldPeriodNanos));
503 }
504 }
505
Test_setActiveConfigWithConstraints(const TestParameters & params)506 void GraphicsComposerHidlTest::Test_setActiveConfigWithConstraints(const TestParameters& params) {
507 for (VtsDisplay& display : mDisplays) {
508 forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
509 setActiveConfig(display, config1);
510 sendRefreshFrame(display, nullptr);
511
512 const auto vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
513 display.get(), config1,
514 IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
515 const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
516 display.get(), config1,
517 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
518 const auto vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
519 display.get(), config2,
520 IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
521 const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
522 display.get(), config2,
523 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
524
525 if (vsyncPeriod1 == vsyncPeriod2) {
526 return; // continue
527 }
528
529 // We don't allow delayed change when changing config groups
530 if (params.delayForChange > 0 && configGroup1 != configGroup2) {
531 return; // continue
532 }
533
534 VsyncPeriodChangeTimeline timeline;
535 IComposerClient::VsyncPeriodChangeConstraints constraints = {
536 .desiredTimeNanos = systemTime() + params.delayForChange,
537 .seamlessRequired = false};
538 EXPECT_EQ(Error::NONE,
539 setActiveConfigWithConstraints(display, config2, constraints, &timeline));
540
541 EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
542 if (configGroup1 == configGroup2) {
543 // Refresh rate should change within a reasonable time
544 constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s;
545 EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
546 kReasonableTimeForChange.count());
547 }
548
549 if (timeline.refreshRequired) {
550 if (params.refreshMiss) {
551 // Miss the refresh frame on purpose to make sure the implementation sends a
552 // callback
553 std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) + 100ms);
554 }
555 sendRefreshFrame(display, &timeline);
556 }
557 waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
558 vsyncPeriod1, vsyncPeriod2);
559
560 // At this point the refresh rate should have changed already, however in rare
561 // cases the implementation might have missed the deadline. In this case a new
562 // timeline should have been provided.
563 auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
564 if (timeline.refreshRequired && params.refreshMiss) {
565 EXPECT_TRUE(newTimeline.has_value());
566 }
567
568 if (newTimeline.has_value()) {
569 if (newTimeline->refreshRequired) {
570 sendRefreshFrame(display, &newTimeline.value());
571 }
572 waitForVsyncPeriodChange(display.get(), newTimeline.value(),
573 constraints.desiredTimeNanos, vsyncPeriod1, vsyncPeriod2);
574 }
575
576 VsyncPeriodNanos vsyncPeriodNanos;
577 EXPECT_EQ(Error::NONE,
578 mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
579 EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
580 });
581 }
582 }
583
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints)584 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints) {
585 Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
586 }
587
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_Delayed)588 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_Delayed) {
589 Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000, // 300ms
590 .refreshMiss = false});
591 }
592
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_MissRefresh)593 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_MissRefresh) {
594 Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
595 }
596
TEST_P(GraphicsComposerHidlTest,setAutoLowLatencyModeBadDisplay)597 TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) {
598 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true));
599 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, false));
600 }
601
TEST_P(GraphicsComposerHidlTest,setAutoLowLatencyMode)602 TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyMode) {
603 for (const auto& display : mDisplays) {
604 std::vector<DisplayCapability> capabilities;
605 const auto error = mComposerClient->getDisplayCapabilities(display.get(), &capabilities);
606 EXPECT_EQ(Error::NONE, error);
607
608 const bool allmSupport =
609 std::find(capabilities.begin(), capabilities.end(),
610 DisplayCapability::AUTO_LOW_LATENCY_MODE) != capabilities.end();
611
612 if (!allmSupport) {
613 EXPECT_EQ(Error::UNSUPPORTED,
614 mComposerClient->setAutoLowLatencyMode(display.get(), true));
615 EXPECT_EQ(Error::UNSUPPORTED,
616 mComposerClient->setAutoLowLatencyMode(display.get(), false));
617 GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display "
618 << std::to_string(display.get()) << ", skipping test";
619 return;
620 }
621
622 EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(display.get(), true));
623 EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(display.get(), false));
624 }
625 }
626
TEST_P(GraphicsComposerHidlTest,getSupportedContentTypesBadDisplay)627 TEST_P(GraphicsComposerHidlTest, getSupportedContentTypesBadDisplay) {
628 std::vector<ContentType> supportedContentTypes;
629 const auto error =
630 mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes);
631 EXPECT_EQ(Error::BAD_DISPLAY, error);
632 }
633
TEST_P(GraphicsComposerHidlTest,getSupportedContentTypes)634 TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) {
635 std::vector<ContentType> supportedContentTypes;
636 for (const auto& display : mDisplays) {
637 supportedContentTypes.clear();
638 const auto error =
639 mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
640 const bool noneSupported =
641 std::find(supportedContentTypes.begin(), supportedContentTypes.end(),
642 ContentType::NONE) != supportedContentTypes.end();
643 EXPECT_EQ(Error::NONE, error);
644 EXPECT_FALSE(noneSupported);
645 }
646 }
647
TEST_P(GraphicsComposerHidlTest,setContentTypeNoneAlwaysAccepted)648 TEST_P(GraphicsComposerHidlTest, setContentTypeNoneAlwaysAccepted) {
649 for (const auto& display : mDisplays) {
650 const auto error = mComposerClient->setContentType(display.get(), ContentType::NONE);
651 EXPECT_NE(Error::UNSUPPORTED, error);
652 }
653 }
654
TEST_P(GraphicsComposerHidlTest,setContentTypeBadDisplay)655 TEST_P(GraphicsComposerHidlTest, setContentTypeBadDisplay) {
656 const auto types = {ContentType::NONE, ContentType::GRAPHICS, ContentType::PHOTO,
657 ContentType::CINEMA, ContentType::GAME};
658 for (auto type : types) {
659 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setContentType(mInvalidDisplayId, type));
660 }
661 }
662
Test_setContentTypeForDisplay(const Display & display,const std::vector<ContentType> & capabilities,const ContentType & contentType,const char * contentTypeStr)663 void GraphicsComposerHidlTest::Test_setContentTypeForDisplay(
664 const Display& display, const std::vector<ContentType>& capabilities,
665 const ContentType& contentType, const char* contentTypeStr) {
666 const bool contentTypeSupport =
667 std::find(capabilities.begin(), capabilities.end(), contentType) != capabilities.end();
668
669 if (!contentTypeSupport) {
670 EXPECT_EQ(Error::UNSUPPORTED, mComposerClient->setContentType(display, contentType));
671 GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
672 << std::to_string(display) << ", skipping test";
673 return;
674 }
675
676 EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, contentType));
677 EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, ContentType::NONE));
678 }
679
Test_setContentType(const ContentType & contentType,const char * contentTypeStr)680 void GraphicsComposerHidlTest::Test_setContentType(const ContentType& contentType,
681 const char* contentTypeStr) {
682 for (const auto& display : mDisplays) {
683 std::vector<ContentType> supportedContentTypes;
684 const auto error =
685 mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
686 EXPECT_EQ(Error::NONE, error);
687
688 Test_setContentTypeForDisplay(display.get(), supportedContentTypes, contentType,
689 contentTypeStr);
690 }
691 }
692
TEST_P(GraphicsComposerHidlTest,setGraphicsContentType)693 TEST_P(GraphicsComposerHidlTest, setGraphicsContentType) {
694 Test_setContentType(ContentType::GRAPHICS, "GRAPHICS");
695 }
696
TEST_P(GraphicsComposerHidlTest,setPhotoContentType)697 TEST_P(GraphicsComposerHidlTest, setPhotoContentType) {
698 Test_setContentType(ContentType::PHOTO, "PHOTO");
699 }
700
TEST_P(GraphicsComposerHidlTest,setCinemaContentType)701 TEST_P(GraphicsComposerHidlTest, setCinemaContentType) {
702 Test_setContentType(ContentType::CINEMA, "CINEMA");
703 }
704
TEST_P(GraphicsComposerHidlTest,setGameContentType)705 TEST_P(GraphicsComposerHidlTest, setGameContentType) {
706 Test_setContentType(ContentType::GAME, "GAME");
707 }
708
709 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlTest);
710 INSTANTIATE_TEST_SUITE_P(
711 PerInstance, GraphicsComposerHidlTest,
712 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
713 android::hardware::PrintInstanceNameToString);
714
TEST_P(GraphicsComposerHidlTest,getLayerGenericMetadataKeys)715 TEST_P(GraphicsComposerHidlTest, getLayerGenericMetadataKeys) {
716 std::vector<IComposerClient::LayerGenericMetadataKey> keys;
717 mComposerClient->getLayerGenericMetadataKeys(&keys);
718
719 std::regex reverseDomainName("^[a-zA-Z-]{2,}(\\.[a-zA-Z0-9-]+)+$");
720 std::unordered_set<std::string> uniqueNames;
721 for (const auto& key : keys) {
722 std::string name(key.name.c_str());
723
724 // Keys must not start with 'android' or 'com.android'
725 ASSERT_FALSE(name.find("android") == 0);
726 ASSERT_FALSE(name.find("com.android") == 0);
727
728 // Keys must be in reverse domain name format
729 ASSERT_TRUE(std::regex_match(name, reverseDomainName));
730
731 // Keys must be unique within this list
732 const auto& [iter, inserted] = uniqueNames.insert(name);
733 ASSERT_TRUE(inserted);
734 }
735 }
736
737 /*
738 * Test that no two display configs are exactly the same.
739 */
TEST_P(GraphicsComposerHidlTest,GetDisplayConfigNoRepetitions)740 TEST_P(GraphicsComposerHidlTest, GetDisplayConfigNoRepetitions) {
741 for (const auto& display : mDisplays) {
742 std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
743 for (int i = 0; i < configs.size(); i++) {
744 for (int j = i + 1; j < configs.size(); j++) {
745 const int32_t width1 = mComposerClient->getDisplayAttribute_2_4(
746 display.get(), configs[i], IComposerClient::Attribute::WIDTH);
747 const int32_t height1 = mComposerClient->getDisplayAttribute_2_4(
748 display.get(), configs[i], IComposerClient::Attribute::HEIGHT);
749 const int32_t vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
750 display.get(), configs[i], IComposerClient::Attribute::VSYNC_PERIOD);
751 const int32_t group1 = mComposerClient->getDisplayAttribute_2_4(
752 display.get(), configs[i], IComposerClient::Attribute::CONFIG_GROUP);
753
754 const int32_t width2 = mComposerClient->getDisplayAttribute_2_4(
755 display.get(), configs[j], IComposerClient::Attribute::WIDTH);
756 const int32_t height2 = mComposerClient->getDisplayAttribute_2_4(
757 display.get(), configs[j], IComposerClient::Attribute::HEIGHT);
758 const int32_t vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
759 display.get(), configs[j], IComposerClient::Attribute::VSYNC_PERIOD);
760 const int32_t group2 = mComposerClient->getDisplayAttribute_2_4(
761 display.get(), configs[j], IComposerClient::Attribute::CONFIG_GROUP);
762
763 ASSERT_FALSE(width1 == width2 && height1 == height2 &&
764 vsyncPeriod1 == vsyncPeriod2 && group1 == group2);
765 }
766 }
767 }
768 }
769
770 } // namespace
771 } // namespace vts
772 } // namespace V2_4
773 } // namespace composer
774 } // namespace graphics
775 } // namespace hardware
776 } // namespace android
777
main(int argc,char ** argv)778 int main(int argc, char** argv) {
779 ::testing::InitGoogleTest(&argc, argv);
780
781 using namespace std::chrono_literals;
782 if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
783 ALOGE("Failed to stop init.svc.surfaceflinger");
784 return -1;
785 }
786
787 return RUN_ALL_TESTS();
788 }
789