blob: 00b578b3f960dd31f02f7105d71eae8e38418cc0 [file] [log] [blame]
ramindaniedf3ef92022-01-07 00:04:23 +00001/**
2 * Copyright (c) 2022, 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
ramindani458e53e2022-02-23 17:30:16 +000017#include "VtsComposerClient.h"
ramindaniedf3ef92022-01-07 00:04:23 +000018#include <aidlcommonsupport/NativeHandle.h>
19#include <android-base/logging.h>
20#include <log/log_main.h>
21
22#undef LOG_TAG
23#define LOG_TAG "VtsComposerClient"
24
25using namespace std::chrono_literals;
26
27namespace aidl::android::hardware::graphics::composer3::vts {
28
29VtsComposerClient::VtsComposerClient(const std::string& name) {
30 SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
31 ALOGE_IF(binder == nullptr, "Could not initialize the service binder");
32 if (binder != nullptr) {
33 mComposer = IComposer::fromBinder(binder);
34 ALOGE_IF(mComposer == nullptr, "Failed to acquire the composer from the binder");
35 }
36}
37
38ScopedAStatus VtsComposerClient::createClient() {
39 if (mComposer == nullptr) {
40 ALOGE("IComposer not initialized");
41 return ScopedAStatus::fromServiceSpecificError(IComposerClient::INVALID_CONFIGURATION);
42 }
43 auto status = mComposer->createClient(&mComposerClient);
44 if (!status.isOk() || mComposerClient == nullptr) {
45 ALOGE("Failed to create client for IComposerClient with %s",
46 status.getDescription().c_str());
47 return status;
48 }
49 mComposerCallback = SharedRefBase::make<GraphicsComposerCallback>();
50 if (mComposerCallback == nullptr) {
51 ALOGE("Unable to create ComposerCallback");
52 return ScopedAStatus::fromServiceSpecificError(IComposerClient::INVALID_CONFIGURATION);
53 }
54 return mComposerClient->registerCallback(mComposerCallback);
55}
56
57bool VtsComposerClient::tearDown() {
58 return verifyComposerCallbackParams() && destroyAllLayers();
59}
60
Brian Lindahl78ff2d62022-12-18 11:21:41 -070061std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() {
62 int32_t version = 1;
63 auto status = mComposerClient->getInterfaceVersion(&version);
64 return {std::move(status), version};
65}
66
ramindaniedf3ef92022-01-07 00:04:23 +000067std::pair<ScopedAStatus, VirtualDisplay> VtsComposerClient::createVirtualDisplay(
68 int32_t width, int32_t height, PixelFormat pixelFormat, int32_t bufferSlotCount) {
69 VirtualDisplay outVirtualDisplay;
70 auto status = mComposerClient->createVirtualDisplay(width, height, pixelFormat, bufferSlotCount,
71 &outVirtualDisplay);
72 if (!status.isOk()) {
73 return {std::move(status), outVirtualDisplay};
74 }
75 return {addDisplayToDisplayResources(outVirtualDisplay.display, /*isVirtual*/ true),
76 outVirtualDisplay};
77}
78
79ScopedAStatus VtsComposerClient::destroyVirtualDisplay(int64_t display) {
80 auto status = mComposerClient->destroyVirtualDisplay(display);
81 if (!status.isOk()) {
82 return status;
83 }
84 mDisplayResources.erase(display);
85 return status;
86}
87
88std::pair<ScopedAStatus, int64_t> VtsComposerClient::createLayer(int64_t display,
89 int32_t bufferSlotCount) {
90 int64_t outLayer;
91 auto status = mComposerClient->createLayer(display, bufferSlotCount, &outLayer);
92
93 if (!status.isOk()) {
94 return {std::move(status), outLayer};
95 }
96 return {addLayerToDisplayResources(display, outLayer), outLayer};
97}
98
99ScopedAStatus VtsComposerClient::destroyLayer(int64_t display, int64_t layer) {
100 auto status = mComposerClient->destroyLayer(display, layer);
101
102 if (!status.isOk()) {
103 return status;
104 }
105 removeLayerFromDisplayResources(display, layer);
106 return status;
107}
108
109std::pair<ScopedAStatus, int32_t> VtsComposerClient::getActiveConfig(int64_t display) {
110 int32_t outConfig;
111 return {mComposerClient->getActiveConfig(display, &outConfig), outConfig};
112}
113
114ScopedAStatus VtsComposerClient::setActiveConfig(VtsDisplay* vtsDisplay, int32_t config) {
115 auto status = mComposerClient->setActiveConfig(vtsDisplay->getDisplayId(), config);
116 if (!status.isOk()) {
117 return status;
118 }
119 return updateDisplayProperties(vtsDisplay, config);
120}
121
122std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayAttribute(
123 int64_t display, int32_t config, DisplayAttribute displayAttribute) {
124 int32_t outDisplayAttribute;
125 return {mComposerClient->getDisplayAttribute(display, config, displayAttribute,
126 &outDisplayAttribute),
127 outDisplayAttribute};
128}
129
130ScopedAStatus VtsComposerClient::setPowerMode(int64_t display, PowerMode powerMode) {
131 return mComposerClient->setPowerMode(display, powerMode);
132}
133
134ScopedAStatus VtsComposerClient::setVsync(int64_t display, bool enable) {
135 return mComposerClient->setVsyncEnabled(display, enable);
136}
137
138void VtsComposerClient::setVsyncAllowed(bool isAllowed) {
139 mComposerCallback->setVsyncAllowed(isAllowed);
140}
141
142std::pair<ScopedAStatus, std::vector<float>> VtsComposerClient::getDataspaceSaturationMatrix(
143 Dataspace dataspace) {
144 std::vector<float> outMatrix;
145 return {mComposerClient->getDataspaceSaturationMatrix(dataspace, &outMatrix), outMatrix};
146}
147
148std::pair<ScopedAStatus, std::vector<CommandResultPayload>> VtsComposerClient::executeCommands(
149 const std::vector<DisplayCommand>& commands) {
150 std::vector<CommandResultPayload> outResultPayload;
151 return {mComposerClient->executeCommands(commands, &outResultPayload),
152 std::move(outResultPayload)};
153}
154
155std::optional<VsyncPeriodChangeTimeline> VtsComposerClient::takeLastVsyncPeriodChangeTimeline() {
156 return mComposerCallback->takeLastVsyncPeriodChangeTimeline();
157}
158
159ScopedAStatus VtsComposerClient::setContentType(int64_t display, ContentType contentType) {
160 return mComposerClient->setContentType(display, contentType);
161}
162
163std::pair<ScopedAStatus, VsyncPeriodChangeTimeline>
164VtsComposerClient::setActiveConfigWithConstraints(VtsDisplay* vtsDisplay, int32_t config,
165 const VsyncPeriodChangeConstraints& constraints) {
166 VsyncPeriodChangeTimeline outTimeline;
167 auto status = mComposerClient->setActiveConfigWithConstraints(
168 vtsDisplay->getDisplayId(), config, constraints, &outTimeline);
169 if (!status.isOk()) {
170 return {std::move(status), outTimeline};
171 }
172 return {updateDisplayProperties(vtsDisplay, config), outTimeline};
173}
174
175std::pair<ScopedAStatus, std::vector<DisplayCapability>> VtsComposerClient::getDisplayCapabilities(
176 int64_t display) {
177 std::vector<DisplayCapability> outCapabilities;
178 return {mComposerClient->getDisplayCapabilities(display, &outCapabilities), outCapabilities};
179}
180
181ScopedAStatus VtsComposerClient::dumpDebugInfo() {
Ady Abraham89d72702022-02-18 17:04:55 -0800182 int pipefds[2];
183 if (pipe(pipefds) < 0) {
184 return ScopedAStatus::fromServiceSpecificError(IComposer::EX_NO_RESOURCES);
185 }
186
187 const auto status = mComposer->dump(pipefds[1], /*args*/ nullptr, /*numArgs*/ 0);
188 close(pipefds[0]);
189 close(pipefds[1]);
190 return ScopedAStatus::fromStatus(status);
ramindaniedf3ef92022-01-07 00:04:23 +0000191}
192
193std::pair<ScopedAStatus, DisplayIdentification> VtsComposerClient::getDisplayIdentificationData(
194 int64_t display) {
195 DisplayIdentification outDisplayIdentification;
196 return {mComposerClient->getDisplayIdentificationData(display, &outDisplayIdentification),
197 outDisplayIdentification};
198}
199
200std::pair<ScopedAStatus, HdrCapabilities> VtsComposerClient::getHdrCapabilities(int64_t display) {
201 HdrCapabilities outHdrCapabilities;
202 return {mComposerClient->getHdrCapabilities(display, &outHdrCapabilities), outHdrCapabilities};
203}
204
205std::pair<ScopedAStatus, std::vector<PerFrameMetadataKey>>
206VtsComposerClient::getPerFrameMetadataKeys(int64_t display) {
207 std::vector<PerFrameMetadataKey> outPerFrameMetadataKeys;
208 return {mComposerClient->getPerFrameMetadataKeys(display, &outPerFrameMetadataKeys),
209 outPerFrameMetadataKeys};
210}
211
212std::pair<ScopedAStatus, ReadbackBufferAttributes> VtsComposerClient::getReadbackBufferAttributes(
213 int64_t display) {
214 ReadbackBufferAttributes outReadbackBufferAttributes;
215 return {mComposerClient->getReadbackBufferAttributes(display, &outReadbackBufferAttributes),
216 outReadbackBufferAttributes};
217}
218
219ScopedAStatus VtsComposerClient::setReadbackBuffer(int64_t display, const native_handle_t* buffer,
220 const ScopedFileDescriptor& releaseFence) {
221 return mComposerClient->setReadbackBuffer(display, ::android::dupToAidl(buffer), releaseFence);
222}
223
224std::pair<ScopedAStatus, ScopedFileDescriptor> VtsComposerClient::getReadbackBufferFence(
225 int64_t display) {
226 ScopedFileDescriptor outReleaseFence;
227 return {mComposerClient->getReadbackBufferFence(display, &outReleaseFence),
228 std::move(outReleaseFence)};
229}
230
231std::pair<ScopedAStatus, std::vector<ColorMode>> VtsComposerClient::getColorModes(int64_t display) {
232 std::vector<ColorMode> outColorModes;
233 return {mComposerClient->getColorModes(display, &outColorModes), outColorModes};
234}
235
236std::pair<ScopedAStatus, std::vector<RenderIntent>> VtsComposerClient::getRenderIntents(
237 int64_t display, ColorMode colorMode) {
238 std::vector<RenderIntent> outRenderIntents;
239 return {mComposerClient->getRenderIntents(display, colorMode, &outRenderIntents),
240 outRenderIntents};
241}
242
243ScopedAStatus VtsComposerClient::setColorMode(int64_t display, ColorMode colorMode,
244 RenderIntent renderIntent) {
245 return mComposerClient->setColorMode(display, colorMode, renderIntent);
246}
247
248std::pair<ScopedAStatus, DisplayContentSamplingAttributes>
249VtsComposerClient::getDisplayedContentSamplingAttributes(int64_t display) {
250 DisplayContentSamplingAttributes outAttributes;
251 return {mComposerClient->getDisplayedContentSamplingAttributes(display, &outAttributes),
252 outAttributes};
253}
254
255ScopedAStatus VtsComposerClient::setDisplayedContentSamplingEnabled(
256 int64_t display, bool isEnabled, FormatColorComponent formatColorComponent,
257 int64_t maxFrames) {
258 return mComposerClient->setDisplayedContentSamplingEnabled(display, isEnabled,
259 formatColorComponent, maxFrames);
260}
261
262std::pair<ScopedAStatus, DisplayContentSample> VtsComposerClient::getDisplayedContentSample(
263 int64_t display, int64_t maxFrames, int64_t timestamp) {
264 DisplayContentSample outDisplayContentSample;
265 return {mComposerClient->getDisplayedContentSample(display, maxFrames, timestamp,
266 &outDisplayContentSample),
267 outDisplayContentSample};
268}
269
270std::pair<ScopedAStatus, DisplayConnectionType> VtsComposerClient::getDisplayConnectionType(
271 int64_t display) {
272 DisplayConnectionType outDisplayConnectionType;
273 return {mComposerClient->getDisplayConnectionType(display, &outDisplayConnectionType),
274 outDisplayConnectionType};
275}
276
277std::pair<ScopedAStatus, std::vector<int32_t>> VtsComposerClient::getDisplayConfigs(
278 int64_t display) {
279 std::vector<int32_t> outConfigs;
280 return {mComposerClient->getDisplayConfigs(display, &outConfigs), outConfigs};
281}
282
283std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayVsyncPeriod(int64_t display) {
284 int32_t outVsyncPeriodNanos;
285 return {mComposerClient->getDisplayVsyncPeriod(display, &outVsyncPeriodNanos),
286 outVsyncPeriodNanos};
287}
288
289ScopedAStatus VtsComposerClient::setAutoLowLatencyMode(int64_t display, bool isEnabled) {
290 return mComposerClient->setAutoLowLatencyMode(display, isEnabled);
291}
292
293std::pair<ScopedAStatus, std::vector<ContentType>> VtsComposerClient::getSupportedContentTypes(
294 int64_t display) {
295 std::vector<ContentType> outContentTypes;
296 return {mComposerClient->getSupportedContentTypes(display, &outContentTypes), outContentTypes};
297}
298
Leon Scroggins IIIde057582022-01-13 12:26:00 -0500299std::pair<ScopedAStatus, std::optional<DisplayDecorationSupport>>
300VtsComposerClient::getDisplayDecorationSupport(int64_t display) {
301 std::optional<DisplayDecorationSupport> outSupport;
302 return {mComposerClient->getDisplayDecorationSupport(display, &outSupport), outSupport};
303}
304
ramindaniedf3ef92022-01-07 00:04:23 +0000305std::pair<ScopedAStatus, int32_t> VtsComposerClient::getMaxVirtualDisplayCount() {
306 int32_t outMaxVirtualDisplayCount;
307 return {mComposerClient->getMaxVirtualDisplayCount(&outMaxVirtualDisplayCount),
308 outMaxVirtualDisplayCount};
309}
310
311std::pair<ScopedAStatus, std::string> VtsComposerClient::getDisplayName(int64_t display) {
312 std::string outDisplayName;
313 return {mComposerClient->getDisplayName(display, &outDisplayName), outDisplayName};
314}
315
316ScopedAStatus VtsComposerClient::setClientTargetSlotCount(int64_t display,
317 int32_t bufferSlotCount) {
318 return mComposerClient->setClientTargetSlotCount(display, bufferSlotCount);
319}
320
321std::pair<ScopedAStatus, std::vector<Capability>> VtsComposerClient::getCapabilities() {
322 std::vector<Capability> outCapabilities;
323 return {mComposer->getCapabilities(&outCapabilities), outCapabilities};
324}
325
326ScopedAStatus VtsComposerClient::setBootDisplayConfig(int64_t display, int32_t config) {
327 return mComposerClient->setBootDisplayConfig(display, config);
328}
329
330ScopedAStatus VtsComposerClient::clearBootDisplayConfig(int64_t display) {
331 return mComposerClient->clearBootDisplayConfig(display);
332}
333
334std::pair<ScopedAStatus, int32_t> VtsComposerClient::getPreferredBootDisplayConfig(
335 int64_t display) {
336 int32_t outConfig;
337 return {mComposerClient->getPreferredBootDisplayConfig(display, &outConfig), outConfig};
338}
339
340std::pair<ScopedAStatus, common::Transform> VtsComposerClient::getDisplayPhysicalOrientation(
341 int64_t display) {
342 common::Transform outDisplayOrientation;
343 return {mComposerClient->getDisplayPhysicalOrientation(display, &outDisplayOrientation),
344 outDisplayOrientation};
345}
346
Sally Qi2600d342022-08-16 12:46:17 -0700347std::pair<ScopedAStatus, composer3::OverlayProperties> VtsComposerClient::getOverlaySupport() {
348 OverlayProperties properties;
349 return {mComposerClient->getOverlaySupport(&properties), properties};
350}
351
ramindaniedf3ef92022-01-07 00:04:23 +0000352ScopedAStatus VtsComposerClient::setIdleTimerEnabled(int64_t display, int32_t timeoutMs) {
353 return mComposerClient->setIdleTimerEnabled(display, timeoutMs);
354}
355
356int32_t VtsComposerClient::getVsyncIdleCount() {
357 return mComposerCallback->getVsyncIdleCount();
358}
359
360int64_t VtsComposerClient::getVsyncIdleTime() {
361 return mComposerCallback->getVsyncIdleTime();
362}
363
364int64_t VtsComposerClient::getInvalidDisplayId() {
365 // returns an invalid display id (one that has not been registered to a
366 // display. Currently assuming that a device will never have close to
367 // std::numeric_limit<uint64_t>::max() displays registered while running tests
368 int64_t id = std::numeric_limits<int64_t>::max();
369 std::vector<int64_t> displays = mComposerCallback->getDisplays();
370 while (id > 0) {
371 if (std::none_of(displays.begin(), displays.end(),
372 [id](const auto& display) { return id == display; })) {
373 return id;
374 }
375 id--;
376 }
377
378 // Although 0 could be an invalid display, a return value of 0
379 // from getInvalidDisplayId means all other ids are in use, a condition which
380 // we are assuming a device will never have
381 EXPECT_NE(0, id);
382 return id;
383}
384
385std::pair<ScopedAStatus, std::vector<VtsDisplay>> VtsComposerClient::getDisplays() {
386 while (true) {
387 // Sleep for a small period of time to allow all built-in displays
388 // to post hotplug events
389 std::this_thread::sleep_for(5ms);
390 std::vector<int64_t> displays = mComposerCallback->getDisplays();
391 if (displays.empty()) {
392 continue;
393 }
394
395 std::vector<VtsDisplay> vtsDisplays;
396 vtsDisplays.reserve(displays.size());
397 for (int64_t display : displays) {
398 auto vtsDisplay = VtsDisplay{display};
399 auto configs = getDisplayConfigs(display);
400 if (!configs.first.isOk()) {
401 ALOGE("Unable to get the displays for test, failed to get the configs "
402 "for display %" PRId64,
403 display);
404 return {std::move(configs.first), vtsDisplays};
405 }
406 for (int config : configs.second) {
407 auto status = updateDisplayProperties(&vtsDisplay, config);
408 if (!status.isOk()) {
409 ALOGE("Unable to get the displays for test, failed to update the properties "
410 "for display %" PRId64,
411 display);
412 return {std::move(status), vtsDisplays};
413 }
414 }
415 vtsDisplays.emplace_back(vtsDisplay);
416 addDisplayToDisplayResources(display, /*isVirtual*/ false);
417 }
418
419 return {ScopedAStatus::ok(), vtsDisplays};
420 }
421}
422
423ScopedAStatus VtsComposerClient::updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config) {
424 const auto width =
425 getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
426 const auto height =
427 getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
428 const auto vsyncPeriod =
429 getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::VSYNC_PERIOD);
430 const auto configGroup =
431 getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::CONFIG_GROUP);
432 if (width.first.isOk() && height.first.isOk() && vsyncPeriod.first.isOk() &&
433 configGroup.first.isOk()) {
434 vtsDisplay->setDimensions(width.second, height.second);
435 vtsDisplay->addDisplayConfig(config, {vsyncPeriod.second, configGroup.second});
436 return ScopedAStatus::ok();
437 }
438
439 LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
440 << ", height: " << height.first.isOk() << ", vsync: " << vsyncPeriod.first.isOk()
441 << ", config: " << configGroup.first.isOk();
442 return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
443}
444
445ScopedAStatus VtsComposerClient::addDisplayToDisplayResources(int64_t display, bool isVirtual) {
446 if (mDisplayResources.insert({display, DisplayResource(isVirtual)}).second) {
447 return ScopedAStatus::ok();
448 }
449
450 ALOGE("Duplicate display id %" PRId64, display);
451 return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_DISPLAY);
452}
453
454ScopedAStatus VtsComposerClient::addLayerToDisplayResources(int64_t display, int64_t layer) {
455 auto resource = mDisplayResources.find(display);
456 if (resource == mDisplayResources.end()) {
457 resource = mDisplayResources.insert({display, DisplayResource(false)}).first;
458 }
459
460 if (!resource->second.layers.insert(layer).second) {
461 ALOGE("Duplicate layer id %" PRId64, layer);
462 return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_LAYER);
463 }
464 return ScopedAStatus::ok();
465}
466
467void VtsComposerClient::removeLayerFromDisplayResources(int64_t display, int64_t layer) {
468 auto resource = mDisplayResources.find(display);
469 if (resource != mDisplayResources.end()) {
470 resource->second.layers.erase(layer);
471 }
472}
473
474bool VtsComposerClient::verifyComposerCallbackParams() {
475 bool isValid = true;
476 if (mComposerCallback != nullptr) {
477 if (mComposerCallback->getInvalidHotplugCount() != 0) {
478 ALOGE("Invalid hotplug count");
479 isValid = false;
480 }
481 if (mComposerCallback->getInvalidRefreshCount() != 0) {
482 ALOGE("Invalid refresh count");
483 isValid = false;
484 }
485 if (mComposerCallback->getInvalidVsyncCount() != 0) {
486 ALOGE("Invalid vsync count");
487 isValid = false;
488 }
489 if (mComposerCallback->getInvalidVsyncPeriodChangeCount() != 0) {
490 ALOGE("Invalid vsync period change count");
491 isValid = false;
492 }
493 if (mComposerCallback->getInvalidSeamlessPossibleCount() != 0) {
494 ALOGE("Invalid seamless possible count");
495 isValid = false;
496 }
497 }
498 return isValid;
499}
500
501bool VtsComposerClient::destroyAllLayers() {
JihCheng Chiud0dbe4e2022-06-11 01:53:11 +0800502 std::unordered_map<int64_t, DisplayResource> physicalDisplays;
503 while (!mDisplayResources.empty()) {
504 const auto& it = mDisplayResources.begin();
505 const auto& [display, resource] = *it;
ramindaniedf3ef92022-01-07 00:04:23 +0000506
JihCheng Chiud0dbe4e2022-06-11 01:53:11 +0800507 while (!resource.layers.empty()) {
508 auto layer = *resource.layers.begin();
ramindaniedf3ef92022-01-07 00:04:23 +0000509 const auto status = destroyLayer(display, layer);
510 if (!status.isOk()) {
511 ALOGE("Unable to destroy all the layers, failed at layer %" PRId64 " with error %s",
512 layer, status.getDescription().c_str());
513 return false;
514 }
515 }
516
517 if (resource.isVirtual) {
518 const auto status = destroyVirtualDisplay(display);
519 if (!status.isOk()) {
520 ALOGE("Unable to destroy the display %" PRId64 " failed with error %s", display,
521 status.getDescription().c_str());
522 return false;
523 }
JihCheng Chiud0dbe4e2022-06-11 01:53:11 +0800524 } else {
525 auto extractIter = mDisplayResources.extract(it);
526 physicalDisplays.insert(std::move(extractIter));
ramindaniedf3ef92022-01-07 00:04:23 +0000527 }
528 }
JihCheng Chiud0dbe4e2022-06-11 01:53:11 +0800529 mDisplayResources.swap(physicalDisplays);
ramindaniedf3ef92022-01-07 00:04:23 +0000530 mDisplayResources.clear();
531 return true;
532}
Leon Scroggins IIIde057582022-01-13 12:26:00 -0500533} // namespace aidl::android::hardware::graphics::composer3::vts