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 }
166
167 struct TestParameters {
168 nsecs_t delayForChange;
169 bool refreshMiss;
170 };
171
172 void Test_setActiveConfigWithConstraints(const TestParameters& params);
173
174 void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline*);
175
176 void waitForVsyncPeriodChange(Display display, const VsyncPeriodChangeTimeline& timeline,
177 int64_t desiredTimeNanos, int64_t oldPeriodNanos,
178 int64_t newPeriodNanos);
179
180 std::unique_ptr<ComposerClient> mComposerClient;
181 std::vector<VtsDisplay> mDisplays;
182 Display mInvalidDisplayId;
183
forEachTwoConfigs(Display display,std::function<void (Config,Config)> func)184 void forEachTwoConfigs(Display display, std::function<void(Config, Config)> func) {
185 const auto displayConfigs = mComposerClient->getDisplayConfigs(display);
186 for (const Config config1 : displayConfigs) {
187 for (const Config config2 : displayConfigs) {
188 if (config1 != config2) {
189 func(config1, config2);
190 }
191 }
192 }
193 }
194
195 void Test_setContentType(const ContentType& contentType, const char* contentTypeStr);
196 void Test_setContentTypeForDisplay(const Display& display,
197 const std::vector<ContentType>& capabilities,
198 const ContentType& contentType, const char* contentTypeStr);
199
setActiveConfigWithConstraints(VtsDisplay & display,Config config,const IComposerClient::VsyncPeriodChangeConstraints & constraints,VsyncPeriodChangeTimeline * timeline)200 Error setActiveConfigWithConstraints(
201 VtsDisplay& display, Config config,
202 const IComposerClient::VsyncPeriodChangeConstraints& constraints,
203 VsyncPeriodChangeTimeline* timeline) {
204 const auto error = mComposerClient->setActiveConfigWithConstraints(display.get(), config,
205 constraints, timeline);
206 if (error == Error::NONE) {
207 const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
208 display.get(), config, IComposerClient::Attribute::WIDTH);
209 const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
210 display.get(), config, IComposerClient::Attribute::HEIGHT);
211 display.setDimensions(displayWidth, displayHeight);
212 }
213 return error;
214 }
215
setActiveConfig(VtsDisplay & display,Config config)216 void setActiveConfig(VtsDisplay& display, Config config) {
217 mComposerClient->setActiveConfig(display.get(), config);
218 const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
219 display.get(), config, IComposerClient::Attribute::WIDTH);
220 const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
221 display.get(), config, IComposerClient::Attribute::HEIGHT);
222 display.setDimensions(displayWidth, displayHeight);
223 }
224
225 private:
226 // use the slot count usually set by SF
227 static constexpr uint32_t kBufferSlotCount = 64;
228
waitForDisplays()229 std::vector<VtsDisplay> waitForDisplays() {
230 while (true) {
231 // Sleep for a small period of time to allow all built-in displays
232 // to post hotplug events
233 std::this_thread::sleep_for(5ms);
234 std::vector<Display> displays = mComposerCallback->getDisplays();
235 if (displays.empty()) {
236 continue;
237 }
238
239 std::vector<VtsDisplay> vtsDisplays;
240 vtsDisplays.reserve(displays.size());
241 for (Display display : displays) {
242 const Config activeConfig = mComposerClient->getActiveConfig(display);
243 const int32_t displayWidth = mComposerClient->getDisplayAttribute_2_4(
244 display, activeConfig, IComposerClient::Attribute::WIDTH);
245 const int32_t displayHeight = mComposerClient->getDisplayAttribute_2_4(
246 display, activeConfig, IComposerClient::Attribute::HEIGHT);
247 vtsDisplays.emplace_back(VtsDisplay{display, displayWidth, displayHeight});
248 }
249
250 return vtsDisplays;
251 }
252 }
253
254 std::unique_ptr<Composer> mComposer;
255 std::unique_ptr<CommandWriterBase> mWriter;
256 std::unique_ptr<TestCommandReader> mReader;
257 sp<GraphicsComposerCallback> mComposerCallback;
258 std::unique_ptr<Gralloc> mGralloc;
259 };
260
TEST_P(GraphicsComposerHidlTest,getDisplayCapabilitiesBadDisplay)261 TEST_P(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
262 std::vector<IComposerClient::DisplayCapability> capabilities;
263 const auto error = mComposerClient->getDisplayCapabilities(mInvalidDisplayId, &capabilities);
264 EXPECT_EQ(Error::BAD_DISPLAY, error);
265 }
266
TEST_P(GraphicsComposerHidlTest,getDisplayCapabilities)267 TEST_P(GraphicsComposerHidlTest, getDisplayCapabilities) {
268 for (const auto& display : mDisplays) {
269 std::vector<IComposerClient::DisplayCapability> capabilities;
270 EXPECT_EQ(Error::NONE,
271 mComposerClient->getDisplayCapabilities(display.get(), &capabilities));
272 }
273 }
274
TEST_P(GraphicsComposerHidlTest,getDisplayConnectionType)275 TEST_P(GraphicsComposerHidlTest, getDisplayConnectionType) {
276 IComposerClient::DisplayConnectionType type;
277 EXPECT_EQ(Error::BAD_DISPLAY,
278 mComposerClient->getDisplayConnectionType(mInvalidDisplayId, &type));
279
280 for (const auto& display : mDisplays) {
281 EXPECT_EQ(Error::NONE, mComposerClient->getDisplayConnectionType(display.get(), &type));
282 }
283 }
284
TEST_P(GraphicsComposerHidlTest,GetDisplayAttribute_2_4)285 TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4) {
286 for (const auto& display : mDisplays) {
287 std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
288 for (auto config : configs) {
289 const std::array<IComposerClient::Attribute, 4> requiredAttributes = {{
290 IComposerClient::Attribute::WIDTH,
291 IComposerClient::Attribute::HEIGHT,
292 IComposerClient::Attribute::VSYNC_PERIOD,
293 IComposerClient::Attribute::CONFIG_GROUP,
294 }};
295 for (auto attribute : requiredAttributes) {
296 mComposerClient->getRaw()->getDisplayAttribute_2_4(
297 display.get(), config, attribute,
298 [&](const auto& tmpError, const auto& value) {
299 EXPECT_EQ(Error::NONE, tmpError);
300 EXPECT_NE(-1, value);
301 });
302 }
303
304 const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
305 IComposerClient::Attribute::DPI_X,
306 IComposerClient::Attribute::DPI_Y,
307 }};
308 for (auto attribute : optionalAttributes) {
309 mComposerClient->getRaw()->getDisplayAttribute_2_4(
310 display.get(), config, attribute, [&](const auto& tmpError, const auto&) {
311 EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
312 });
313 }
314 }
315 }
316 }
317
TEST_P(GraphicsComposerHidlTest,getDisplayVsyncPeriod_BadDisplay)318 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
319 VsyncPeriodNanos vsyncPeriodNanos;
320 EXPECT_EQ(Error::BAD_DISPLAY,
321 mComposerClient->getDisplayVsyncPeriod(mInvalidDisplayId, &vsyncPeriodNanos));
322 }
323
TEST_P(GraphicsComposerHidlTest,getDisplayVsyncPeriod)324 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod) {
325 for (VtsDisplay& display : mDisplays) {
326 for (Config config : mComposerClient->getDisplayConfigs(display.get())) {
327 VsyncPeriodNanos expectedVsyncPeriodNanos = mComposerClient->getDisplayAttribute_2_4(
328 display.get(), config,
329 IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
330
331 VsyncPeriodChangeTimeline timeline;
332 IComposerClient::VsyncPeriodChangeConstraints constraints;
333
334 constraints.desiredTimeNanos = systemTime();
335 constraints.seamlessRequired = false;
336 EXPECT_EQ(Error::NONE,
337 setActiveConfigWithConstraints(display, config, constraints, &timeline));
338
339 if (timeline.refreshRequired) {
340 sendRefreshFrame(display, &timeline);
341 }
342 waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
343 expectedVsyncPeriodNanos);
344
345 VsyncPeriodNanos vsyncPeriodNanos;
346 int retryCount = 100;
347 do {
348 std::this_thread::sleep_for(10ms);
349 vsyncPeriodNanos = 0;
350 EXPECT_EQ(Error::NONE,
351 mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
352 --retryCount;
353 } while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
354
355 EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
356
357 // Make sure that the vsync period stays the same if the active config is not changed.
358 auto timeout = 1ms;
359 for (int i = 0; i < 10; i++) {
360 std::this_thread::sleep_for(timeout);
361 timeout *= 2;
362 vsyncPeriodNanos = 0;
363 EXPECT_EQ(Error::NONE,
364 mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
365 EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
366 }
367 }
368 }
369 }
370
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_BadDisplay)371 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_BadDisplay) {
372 VsyncPeriodChangeTimeline timeline;
373 IComposerClient::VsyncPeriodChangeConstraints constraints;
374
375 constraints.seamlessRequired = false;
376 constraints.desiredTimeNanos = systemTime();
377
378 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setActiveConfigWithConstraints(
379 mInvalidDisplayId, Config(0), constraints, &timeline));
380 }
381
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_BadConfig)382 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_BadConfig) {
383 VsyncPeriodChangeTimeline timeline;
384 IComposerClient::VsyncPeriodChangeConstraints constraints;
385
386 constraints.seamlessRequired = false;
387 constraints.desiredTimeNanos = systemTime();
388
389 for (VtsDisplay& display : mDisplays) {
390 Config invalidConfigId = GetInvalidConfigId(display.get());
391 EXPECT_EQ(Error::BAD_CONFIG,
392 setActiveConfigWithConstraints(display, invalidConfigId, constraints, &timeline));
393 }
394 }
395
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_SeamlessNotAllowed)396 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
397 VsyncPeriodChangeTimeline timeline;
398 IComposerClient::VsyncPeriodChangeConstraints constraints;
399
400 constraints.seamlessRequired = true;
401 constraints.desiredTimeNanos = systemTime();
402
403 for (VtsDisplay& display : mDisplays) {
404 forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
405 const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
406 display.get(), config1,
407 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
408 const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
409 display.get(), config2,
410 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
411 if (configGroup1 != configGroup2) {
412 setActiveConfig(display, config1);
413 sendRefreshFrame(display, nullptr);
414 EXPECT_EQ(Error::SEAMLESS_NOT_ALLOWED,
415 setActiveConfigWithConstraints(display, config2, constraints, &timeline));
416 }
417 });
418 }
419 }
420
toTimePoint(nsecs_t time)421 static inline auto toTimePoint(nsecs_t time) {
422 return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
423 }
424
sendRefreshFrame(const VtsDisplay & display,const VsyncPeriodChangeTimeline * timeline)425 void GraphicsComposerHidlTest::sendRefreshFrame(const VtsDisplay& display,
426 const VsyncPeriodChangeTimeline* timeline) {
427 if (timeline != nullptr) {
428 // Refresh time should be before newVsyncAppliedTimeNanos
429 EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
430
431 std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
432 }
433
434 mWriter->selectDisplay(display.get());
435 mComposerClient->setPowerMode(display.get(), V2_1::IComposerClient::PowerMode::ON);
436 mComposerClient->setColorMode_2_3(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
437
438 IComposerClient::FRect displayCrop = display.getCrop();
439 int32_t displayWidth = static_cast<int32_t>(std::ceilf(displayCrop.right - displayCrop.left));
440 int32_t displayHeight = static_cast<int32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
441 Layer layer;
442 ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(display.get(), kBufferSlotCount));
443
444 {
445 auto handle = allocate(displayWidth, displayHeight);
446 ASSERT_NE(nullptr, handle.get());
447
448 mWriter->selectLayer(layer);
449 mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
450 mWriter->setLayerDisplayFrame(display.getFrameRect());
451 mWriter->setLayerPlaneAlpha(1);
452 mWriter->setLayerSourceCrop(display.getCrop());
453 mWriter->setLayerTransform(static_cast<Transform>(0));
454 mWriter->setLayerVisibleRegion(
455 std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
456 mWriter->setLayerZOrder(10);
457 mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
458 mWriter->setLayerSurfaceDamage(
459 std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
460 mWriter->setLayerBuffer(0, handle.get(), -1);
461 mWriter->setLayerDataspace(Dataspace::UNKNOWN);
462
463 mWriter->validateDisplay();
464 execute();
465 ASSERT_EQ(0, mReader->mErrors.size());
466 mReader->mCompositionChanges.clear();
467
468 mWriter->presentDisplay();
469 execute();
470 ASSERT_EQ(0, mReader->mErrors.size());
471 }
472
473 {
474 auto handle = allocate(displayWidth, displayHeight);
475 ASSERT_NE(nullptr, handle.get());
476
477 mWriter->selectLayer(layer);
478 mWriter->setLayerBuffer(0, handle.get(), -1);
479 mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
480 mWriter->validateDisplay();
481 execute();
482 ASSERT_EQ(0, mReader->mErrors.size());
483 mReader->mCompositionChanges.clear();
484
485 mWriter->presentDisplay();
486 execute();
487 }
488
489 ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(display.get(), layer));
490 }
491
waitForVsyncPeriodChange(Display display,const VsyncPeriodChangeTimeline & timeline,int64_t desiredTimeNanos,int64_t oldPeriodNanos,int64_t newPeriodNanos)492 void GraphicsComposerHidlTest::waitForVsyncPeriodChange(Display display,
493 const VsyncPeriodChangeTimeline& timeline,
494 int64_t desiredTimeNanos,
495 int64_t oldPeriodNanos,
496 int64_t newPeriodNanos) {
497 const auto CHANGE_DEADLINE = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
498 while (std::chrono::steady_clock::now() <= CHANGE_DEADLINE) {
499 VsyncPeriodNanos vsyncPeriodNanos;
500 EXPECT_EQ(Error::NONE, mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
501 if (systemTime() <= desiredTimeNanos) {
502 EXPECT_EQ(vsyncPeriodNanos, oldPeriodNanos);
503 } else if (vsyncPeriodNanos == newPeriodNanos) {
504 break;
505 }
506 std::this_thread::sleep_for(std::chrono::nanoseconds(oldPeriodNanos));
507 }
508 }
509
Test_setActiveConfigWithConstraints(const TestParameters & params)510 void GraphicsComposerHidlTest::Test_setActiveConfigWithConstraints(const TestParameters& params) {
511 for (VtsDisplay& display : mDisplays) {
512 forEachTwoConfigs(display.get(), [&](Config config1, Config config2) {
513 setActiveConfig(display, config1);
514 sendRefreshFrame(display, nullptr);
515
516 const auto vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
517 display.get(), config1,
518 IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
519 const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
520 display.get(), config1,
521 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
522 const auto vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
523 display.get(), config2,
524 IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
525 const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
526 display.get(), config2,
527 IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
528
529 if (vsyncPeriod1 == vsyncPeriod2) {
530 return; // continue
531 }
532
533 // We don't allow delayed change when changing config groups
534 if (params.delayForChange > 0 && configGroup1 != configGroup2) {
535 return; // continue
536 }
537
538 VsyncPeriodChangeTimeline timeline;
539 IComposerClient::VsyncPeriodChangeConstraints constraints = {
540 .desiredTimeNanos = systemTime() + params.delayForChange,
541 .seamlessRequired = false};
542 EXPECT_EQ(Error::NONE,
543 setActiveConfigWithConstraints(display, config2, constraints, &timeline));
544
545 EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
546 // Refresh rate should change within a reasonable time
547 constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s; // 1 second
548 EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
549 kReasonableTimeForChange.count());
550
551 if (timeline.refreshRequired) {
552 if (params.refreshMiss) {
553 // Miss the refresh frame on purpose to make sure the implementation sends a
554 // callback
555 std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) + 100ms);
556 }
557 sendRefreshFrame(display, &timeline);
558 }
559 waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
560 vsyncPeriod1, vsyncPeriod2);
561
562 // At this point the refresh rate should have changed already, however in rare
563 // cases the implementation might have missed the deadline. In this case a new
564 // timeline should have been provided.
565 auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
566 if (timeline.refreshRequired && params.refreshMiss) {
567 EXPECT_TRUE(newTimeline.has_value());
568 }
569
570 if (newTimeline.has_value()) {
571 if (newTimeline->refreshRequired) {
572 sendRefreshFrame(display, &newTimeline.value());
573 }
574 waitForVsyncPeriodChange(display.get(), newTimeline.value(),
575 constraints.desiredTimeNanos, vsyncPeriod1, vsyncPeriod2);
576 }
577
578 VsyncPeriodNanos vsyncPeriodNanos;
579 EXPECT_EQ(Error::NONE,
580 mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos));
581 EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
582 });
583 }
584 }
585
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints)586 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints) {
587 Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
588 }
589
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_Delayed)590 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_Delayed) {
591 Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000, // 300ms
592 .refreshMiss = false});
593 }
594
TEST_P(GraphicsComposerHidlTest,setActiveConfigWithConstraints_MissRefresh)595 TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_MissRefresh) {
596 Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
597 }
598
TEST_P(GraphicsComposerHidlTest,setAutoLowLatencyModeBadDisplay)599 TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) {
600 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true));
601 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, false));
602 }
603
TEST_P(GraphicsComposerHidlTest,setAutoLowLatencyMode)604 TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyMode) {
605 for (const auto& display : mDisplays) {
606 std::vector<DisplayCapability> capabilities;
607 const auto error = mComposerClient->getDisplayCapabilities(display.get(), &capabilities);
608 EXPECT_EQ(Error::NONE, error);
609
610 const bool allmSupport =
611 std::find(capabilities.begin(), capabilities.end(),
612 DisplayCapability::AUTO_LOW_LATENCY_MODE) != capabilities.end();
613
614 if (!allmSupport) {
615 EXPECT_EQ(Error::UNSUPPORTED,
616 mComposerClient->setAutoLowLatencyMode(display.get(), true));
617 EXPECT_EQ(Error::UNSUPPORTED,
618 mComposerClient->setAutoLowLatencyMode(display.get(), false));
619 GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display "
620 << std::to_string(display.get()) << ", skipping test";
621 return;
622 }
623
624 EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(display.get(), true));
625 EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(display.get(), false));
626 }
627 }
628
TEST_P(GraphicsComposerHidlTest,getSupportedContentTypesBadDisplay)629 TEST_P(GraphicsComposerHidlTest, getSupportedContentTypesBadDisplay) {
630 std::vector<ContentType> supportedContentTypes;
631 const auto error =
632 mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes);
633 EXPECT_EQ(Error::BAD_DISPLAY, error);
634 }
635
TEST_P(GraphicsComposerHidlTest,getSupportedContentTypes)636 TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) {
637 std::vector<ContentType> supportedContentTypes;
638 for (const auto& display : mDisplays) {
639 supportedContentTypes.clear();
640 const auto error =
641 mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
642 const bool noneSupported =
643 std::find(supportedContentTypes.begin(), supportedContentTypes.end(),
644 ContentType::NONE) != supportedContentTypes.end();
645 EXPECT_EQ(Error::NONE, error);
646 EXPECT_FALSE(noneSupported);
647 }
648 }
649
TEST_P(GraphicsComposerHidlTest,setContentTypeNoneAlwaysAccepted)650 TEST_P(GraphicsComposerHidlTest, setContentTypeNoneAlwaysAccepted) {
651 for (const auto& display : mDisplays) {
652 const auto error = mComposerClient->setContentType(display.get(), ContentType::NONE);
653 EXPECT_NE(Error::UNSUPPORTED, error);
654 }
655 }
656
TEST_P(GraphicsComposerHidlTest,setContentTypeBadDisplay)657 TEST_P(GraphicsComposerHidlTest, setContentTypeBadDisplay) {
658 const auto types = {ContentType::NONE, ContentType::GRAPHICS, ContentType::PHOTO,
659 ContentType::CINEMA, ContentType::GAME};
660 for (auto type : types) {
661 EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setContentType(mInvalidDisplayId, type));
662 }
663 }
664
Test_setContentTypeForDisplay(const Display & display,const std::vector<ContentType> & capabilities,const ContentType & contentType,const char * contentTypeStr)665 void GraphicsComposerHidlTest::Test_setContentTypeForDisplay(
666 const Display& display, const std::vector<ContentType>& capabilities,
667 const ContentType& contentType, const char* contentTypeStr) {
668 const bool contentTypeSupport =
669 std::find(capabilities.begin(), capabilities.end(), contentType) != capabilities.end();
670
671 if (!contentTypeSupport) {
672 EXPECT_EQ(Error::UNSUPPORTED, mComposerClient->setContentType(display, contentType));
673 GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
674 << std::to_string(display) << ", skipping test";
675 return;
676 }
677
678 EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, contentType));
679 EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, ContentType::NONE));
680 }
681
Test_setContentType(const ContentType & contentType,const char * contentTypeStr)682 void GraphicsComposerHidlTest::Test_setContentType(const ContentType& contentType,
683 const char* contentTypeStr) {
684 for (const auto& display : mDisplays) {
685 std::vector<ContentType> supportedContentTypes;
686 const auto error =
687 mComposerClient->getSupportedContentTypes(display.get(), &supportedContentTypes);
688 EXPECT_EQ(Error::NONE, error);
689
690 Test_setContentTypeForDisplay(display.get(), supportedContentTypes, contentType,
691 contentTypeStr);
692 }
693 }
694
TEST_P(GraphicsComposerHidlTest,setGraphicsContentType)695 TEST_P(GraphicsComposerHidlTest, setGraphicsContentType) {
696 Test_setContentType(ContentType::GRAPHICS, "GRAPHICS");
697 }
698
TEST_P(GraphicsComposerHidlTest,setPhotoContentType)699 TEST_P(GraphicsComposerHidlTest, setPhotoContentType) {
700 Test_setContentType(ContentType::PHOTO, "PHOTO");
701 }
702
TEST_P(GraphicsComposerHidlTest,setCinemaContentType)703 TEST_P(GraphicsComposerHidlTest, setCinemaContentType) {
704 Test_setContentType(ContentType::CINEMA, "CINEMA");
705 }
706
TEST_P(GraphicsComposerHidlTest,setGameContentType)707 TEST_P(GraphicsComposerHidlTest, setGameContentType) {
708 Test_setContentType(ContentType::GAME, "GAME");
709 }
710
711 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerHidlTest);
712 INSTANTIATE_TEST_SUITE_P(
713 PerInstance, GraphicsComposerHidlTest,
714 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
715 android::hardware::PrintInstanceNameToString);
716
TEST_P(GraphicsComposerHidlTest,getLayerGenericMetadataKeys)717 TEST_P(GraphicsComposerHidlTest, getLayerGenericMetadataKeys) {
718 std::vector<IComposerClient::LayerGenericMetadataKey> keys;
719 mComposerClient->getLayerGenericMetadataKeys(&keys);
720
721 std::regex reverseDomainName("^[a-zA-Z-]{2,}(\\.[a-zA-Z0-9-]+)+$");
722 std::unordered_set<std::string> uniqueNames;
723 for (const auto& key : keys) {
724 std::string name(key.name.c_str());
725
726 // Keys must not start with 'android' or 'com.android'
727 ASSERT_FALSE(name.find("android") == 0);
728 ASSERT_FALSE(name.find("com.android") == 0);
729
730 // Keys must be in reverse domain name format
731 ASSERT_TRUE(std::regex_match(name, reverseDomainName));
732
733 // Keys must be unique within this list
734 const auto& [iter, inserted] = uniqueNames.insert(name);
735 ASSERT_TRUE(inserted);
736 }
737 }
738
739 } // namespace
740 } // namespace vts
741 } // namespace V2_4
742 } // namespace composer
743 } // namespace graphics
744 } // namespace hardware
745 } // namespace android
746
main(int argc,char ** argv)747 int main(int argc, char** argv) {
748 ::testing::InitGoogleTest(&argc, argv);
749
750 using namespace std::chrono_literals;
751 if (!android::base::WaitForProperty("init.svc.surfaceflinger", "stopped", 10s)) {
752 ALOGE("Failed to stop init.svc.surfaceflinger");
753 return -1;
754 }
755
756 return RUN_ALL_TESTS();
757 }
758