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